diff options
| author | David Woodhouse <dwmw2@shinybook.infradead.org> | 2004-06-23 17:22:50 +0100 |
|---|---|---|
| committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2004-06-23 17:22:50 +0100 |
| commit | 35820ceb46695ccaabaa666d65671489d732129b (patch) | |
| tree | 0f572684d9efae577f6b882efb7e6ea971969197 | |
| parent | e98c260c2e1e231b0453782c71f59be1d82db8af (diff) | |
| parent | f4897eb32ff3d6629e53f67e30d88bb8736b7148 (diff) | |
Merge shinybook.infradead.org:/home/dwmw2/bk/linus-2.5
into shinybook.infradead.org:/home/dwmw2/bk/85xx-2.6
314 files changed, 5559 insertions, 3505 deletions
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index d5ee998d6317..0257f2566e43 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -2377,16 +2377,16 @@ Your cooperation is appreciated. 1 = /dev/gpib1 Second GPIB bus ... -160 block Carmel 8-port SATA Disks on First Controller - 0 = /dev/carmel/0 SATA disk 0 whole disk - 1 = /dev/carmel/0p1 SATA disk 0 partition 1 +160 block Promise SX8 8-port SATA Disks on First Controller + 0 = /dev/sx8/0 SATA disk 0 whole disk + 1 = /dev/sx8/0p1 SATA disk 0 partition 1 ... - 31 = /dev/carmel/0p31 SATA disk 0 partition 31 + 31 = /dev/sx8/0p31 SATA disk 0 partition 31 - 32 = /dev/carmel/1 SATA disk 1 whole disk - 64 = /dev/carmel/2 SATA disk 2 whole disk + 32 = /dev/sx8/1 SATA disk 1 whole disk + 64 = /dev/sx8/2 SATA disk 2 whole disk ... - 224 = /dev/carmel/7 SATA disk 7 whole disk + 224 = /dev/sx8/7 SATA disk 7 whole disk Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on @@ -2400,16 +2400,16 @@ Your cooperation is appreciated. 17 = /dev/irlpt1 Second IrLPT device ... -161 block Carmel 8-port SATA Disks on Second Controller - 0 = /dev/carmel/8 SATA disk 8 whole disk - 1 = /dev/carmel/8p1 SATA disk 8 partition 1 +161 block Promise SX8 8-port SATA Disks on Second Controller + 0 = /dev/sx8/8 SATA disk 8 whole disk + 1 = /dev/sx8/8p1 SATA disk 8 partition 1 ... - 31 = /dev/carmel/8p31 SATA disk 8 partition 31 + 31 = /dev/sx8/8p31 SATA disk 8 partition 31 - 32 = /dev/carmel/9 SATA disk 9 whole disk - 64 = /dev/carmel/10 SATA disk 10 whole disk + 32 = /dev/sx8/9 SATA disk 9 whole disk + 64 = /dev/sx8/10 SATA disk 10 whole disk ... - 224 = /dev/carmel/15 SATA disk 15 whole disk + 224 = /dev/sx8/15 SATA disk 15 whole disk Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on diff --git a/MAINTAINERS b/MAINTAINERS index 1b254cd76b4b..9d6c1955bd14 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -703,6 +703,12 @@ M: jrv@vanzandt.mv.com L: blinux-list@redhat.com S: Maintained +DRIVER CORE, KOBJECTS, AND SYSFS +P: Greg Kroah-Hartman +M: greg@kroah.com +L: linux-kernel@vger.kernel.org +S: Supported + DRM DRIVERS L: dri-devel@lists.sourceforge.net S: Supported diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a9a5535fffa9..ae7e19db4e3d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -72,9 +72,6 @@ choice prompt "ARM system type" default ARCH_RPC -config ARCH_ADIFCC - bool "ADIFCC-based" - config ARCH_CLPS7500 bool "Cirrus-CL-PS7500FE" @@ -191,6 +188,11 @@ config ARCH_ACORN depends on ARCH_RPC default y +config TIMER_ACORN + bool + depends on ARCH_ACORN || ARCH_CLPS7500 + default y + ##################################################################### # Footbridge support config FOOTBRIDGE diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 954004064480..d8a4d37287cb 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -88,7 +88,6 @@ textaddr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000 machine-$(CONFIG_ARCH_CLPS711X) := clps711x textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 machine-$(CONFIG_ARCH_IOP3XX) := iop3xx - machine-$(CONFIG_ARCH_ADIFCC) := adifcc machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx machine-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_S3C2410) := s3c2410 diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 72be85c543ed..8c42a9132ce3 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -49,8 +49,6 @@ initrd_phys-$(CONFIG_ARCH_SA1100) := 0xc0800000 zreladdr-$(CONFIG_ARCH_PXA) := 0xa0008000 zreladdr-$(CONFIG_ARCH_IOP3XX) := 0xa0008000 params_phys-$(CONFIG_ARCH_IOP3XX) := 0xa0000100 - zreladdr-$(CONFIG_ARCH_ADIFCC) := 0xc0008000 -params_phys-$(CONFIG_ARCH_ADIFCC) := 0xc0000100 zreladdr-$(CONFIG_ARCH_IXP4XX) := 0x00008000 params-phys-$(CONFIG_ARCH_IXP4XX) := 0x00000100 zreladdr-$(CONFIG_ARCH_OMAP) := 0x10008000 diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index e6656d4ef5c8..f9194499e863 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -66,7 +66,4 @@ __XScale_start: mov r7, #MACH_TYPE_IQ80310 #endif -#ifdef CONFIG_ARCH_ADI_EVB - mov r7, #MACH_TYPE_ADI_EVB -#endif diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 72a12c24689f..a0648d979d08 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_ICST525) += icst525.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o +obj-$(CONFIG_TIMER_ACORN) += time-acorn.o diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index ee4b692e1d68..83eee1aa27e7 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -610,7 +610,7 @@ out: * %-EBUSY physical address already marked in-use. * %0 successful. */ -static int __init +static int __sa1111_probe(struct device *me, struct resource *mem, int irq) { struct sa1111 *sachip; diff --git a/arch/arm/kernel/time-acorn.c b/arch/arm/common/time-acorn.c index a4dd9f0557ff..eb06282962eb 100644 --- a/arch/arm/kernel/time-acorn.c +++ b/arch/arm/common/time-acorn.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/time-acorn.c + * linux/arch/arm/common/time-acorn.c * * Copyright (c) 1996-2000 Russell King. * @@ -11,6 +11,7 @@ * 24-Sep-1996 RMK Created * 10-Oct-1996 RMK Brought up to date with arch-sa110eval * 04-Dec-1997 RMK Updated for new arch/arm/time.c + * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500 */ #include <linux/timex.h> #include <linux/init.h> @@ -19,7 +20,7 @@ #include <asm/io.h> #include <asm/hardware/ioc.h> -extern unsigned long (*gettimeoffset)(void); +#include <asm/mach/time.h> static unsigned long ioctime_gettimeoffset(void) { diff --git a/arch/arm/configs/adi_evb_defconfig b/arch/arm/configs/adi_evb_defconfig deleted file mode 100644 index bae486663bb4..000000000000 --- a/arch/arm/configs/adi_evb_defconfig +++ /dev/null @@ -1,678 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set - -# -# System Type -# -CONFIG_ARCH_ADIFCC=y -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 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_IOP310 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set - -# -# Archimedes/A5000 Implementations -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -CONFIG_ARCH_ADI_EVB=y -CONFIG_XSCALE_PMU_TIMER=y -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -# CONFIG_CPU_32v4 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_XSCALE=y -CONFIG_ARM_THUMB=y -# CONFIG_XSCALE_TOOLS is not set -CONFIG_XSCALE_WRITE_ALLOC=y -CONFIG_XSCALE_PMU=y -CONFIG_ARM_THUMB=y -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mtdblock1 mem=32M initrd=0xc0800000,3M" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set -# CONFIG_MTD_AFS_PARTS is not set -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -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_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -CONFIG_MTD_ADI_EVB=y -# CONFIG_MTD_PCI is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -# CONFIG_PACKET is not set -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y -# CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER 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 - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_BIT_SA1100_GPIO is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_NFS_FS is not set -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set -# CONFIG_ZLIB_FS_INFLATE is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_SA1111 is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_SLAB=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 991c219b347c..1a85e39d79be 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -11,8 +11,7 @@ obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \ time.o traps.o obj-$(CONFIG_APM) += apm.o -obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o -obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o +obj-$(CONFIG_ARCH_ACORN) += ecard.o obj-$(CONFIG_FOOTBRIDGE) += isa.o obj-$(CONFIG_FIQ) += fiq.o obj-$(CONFIG_MODULES) += armksyms.o module.o diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index 22b78368d0cc..822dbde5af8c 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -439,32 +439,6 @@ #endif .endm -#elif defined(CONFIG_ARCH_ADI_EVB) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - mov \rx, #0x00400000 @ physical base address - orrne \rx, \rx, #0xff000000 @ virtual base - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x5] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x6] - tst \rd, #0x10 - beq 1001b - .endm - #elif defined(CONFIG_ARCH_IXP4XX) .macro addruart,rx diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index c8a5e0f87bf8..e483bc9b00c4 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -562,7 +562,7 @@ ENTRY(soft_irq_mask) .macro irq_prio_table .endm -#elif defined(CONFIG_ARCH_IOP310) || defined(CONFIG_ARCH_ADIFCC) +#elif defined(CONFIG_ARCH_IOP310) .macro disable_fiq .endm diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1cff09a5537a..d159659677b0 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/root_dev.h> #include <linux/cpu.h> +#include <linux/interrupt.h> #include <asm/elf.h> #include <asm/hardware.h> @@ -34,6 +35,7 @@ #include <asm/mach/arch.h> #include <asm/mach/irq.h> +#include <asm/mach/time.h> #ifndef MEM_SIZE #define MEM_SIZE (16*1024*1024) @@ -727,6 +729,7 @@ void __init setup_arch(char **cmdline_p) * Set up various architecture-specific pointers */ init_arch_irq = mdesc->init_irq; + init_arch_time = mdesc->init_time; init_machine = mdesc->init_machine; #ifdef CONFIG_VT diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index bfed0f453304..efcb44a9e6ab 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -27,12 +27,15 @@ #include <linux/errno.h> #include <linux/profile.h> #include <linux/sysdev.h> +#include <linux/timer.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/leds.h> +#include <asm/mach/time.h> + u64 jiffies_64 = INITIAL_JIFFIES; EXPORT_SYMBOL(jiffies_64); @@ -49,15 +52,11 @@ EXPORT_SYMBOL(rtc_lock); /* change this if you have some constant time drift */ #define USECS_PER_JIFFY (1000000/HZ) -static int dummy_set_rtc(void) -{ - return 0; -} /* * hook for setting the RTC's idea of the current time. */ -int (*set_rtc)(void) = dummy_set_rtc; +int (*set_rtc)(void); static unsigned long dummy_gettimeoffset(void) { @@ -238,7 +237,7 @@ EXPORT_SYMBOL(leds_event); #endif #ifdef CONFIG_LEDS_TIMER -static void do_leds(void) +static inline void do_leds(void) { static unsigned int count = 50; @@ -248,7 +247,7 @@ static void do_leds(void) } } #else -#define do_leds() +#define do_leds() #endif void do_gettimeofday(struct timeval *tv) @@ -316,12 +315,18 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); -static struct irqaction timer_irq = { - .name = "timer", - .flags = SA_INTERRUPT, -}; +void timer_tick(struct pt_regs *regs) +{ + do_profile(regs); + do_leds(); + do_set_rtc(); + do_timer(regs); +} + +void (*init_arch_time)(void); + +void __init time_init(void) +{ + init_arch_time(); +} -/* - * Include architecture specific code - */ -#include <asm/arch/time.h> diff --git a/arch/arm/mach-adifcc/Makefile b/arch/arm/mach-adifcc/Makefile deleted file mode 100644 index d8c1959e9483..000000000000 --- a/arch/arm/mach-adifcc/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := arch.o irq.o mm.o -obj-m := -obj-n := -obj- := - diff --git a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c deleted file mode 100644 index bfc59556d9da..000000000000 --- a/arch/arm/mach-adifcc/arch.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * linux/arch/arm/mach-adifcc/arch.c - * - * Copyright (C) 2001 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/config.h> -#include <linux/init.h> -#include <linux/major.h> -#include <linux/fs.h> - -#include <asm/setup.h> -#include <asm/memory.h> -#include <asm/hardware.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> - -extern void adifcc_map_io(void); -extern void adifcc_init_irq(void); - -#ifdef CONFIG_ARCH_ADI_EVB -MACHINE_START(ADI_EVB, "ADI 80200FCC Evaluation Board") - MAINTAINER("MontaVista Software Inc.") - BOOT_MEM(0xc0000000, 0x00400000, 0xff400000) - MAPIO(adifcc_map_io) - INITIRQ(adifcc_init_irq) -MACHINE_END -#endif - diff --git a/arch/arm/mach-adifcc/irq.c b/arch/arm/mach-adifcc/irq.c deleted file mode 100644 index 4163c602dc2f..000000000000 --- a/arch/arm/mach-adifcc/irq.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * linux/arch/arm/mach-xscale/irq.c - * - * Author: Deepak Saxena - * Copyright: (C) 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Based on IOP80310 code. Currently there's nothing more than the - * 80200 on chip interrupts. That'll change once the hardware adds - * support for PCI though. - */ -#include <linux/init.h> -#include <linux/interrupt.h> - -#include <asm/mach/irq.h> -#include <asm/irq.h> -#include <asm/hardware.h> - -static void xs80200_irq_mask (unsigned int irq) -{ - long INTCTL; - asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL)); - switch (irq) { - case IRQ_XS80200_BCU: INTCTL &= ~(1<<3); break; - case IRQ_XS80200_PMU: INTCTL &= ~(1<<2); break; - case IRQ_XS80200_EXTIRQ: INTCTL &= ~(1<<1); break; - case IRQ_XS80200_EXTFIQ: INTCTL &= ~(1<<0); break; - } - asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL)); -} - -static void xs80200_irq_unmask (unsigned int irq) -{ - long INTCTL; - asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL)); - switch (irq) { - case IRQ_XS80200_BCU: INTCTL |= (1<<3); break; - case IRQ_XS80200_PMU: INTCTL |= (1<<2); break; - case IRQ_XS80200_EXTIRQ: INTCTL |= (1<<1); break; - case IRQ_XS80200_EXTFIQ: INTCTL |= (1<<0); break; - } - asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL)); -} - -void __init adifcc_init_irq(void) -{ - int i; - - for (i = 0; i < NR_XS80200_IRQS; i++) { - irq_desc[i].valid = 1; - irq_desc[i].probe_ok = 0; - irq_desc[i].mask_ack = xs80200_irq_mask; - irq_desc[i].mask = xs80200_irq_mask; - irq_desc[i].unmask = xs80200_irq_unmask; - } -} - - diff --git a/arch/arm/mach-adifcc/mm.c b/arch/arm/mach-adifcc/mm.c deleted file mode 100644 index a81a9794ff10..000000000000 --- a/arch/arm/mach-adifcc/mm.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * linux/arch/arm/mach-xscale/mm.c - */ -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/init.h> - -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> - -#include <asm/mach/map.h> - - -static struct map_desc adifcc_io_desc[] __initdata = { - /* on-board devices */ - { 0xff400000, 0x00400000, 0x00300000, MT_DEVICE } -}; - -void __init adifcc_map_io(void) -{ - iotable_init(adifcc_io_desc, ARRAY_SIZE(adifcc_io_desc)); -} diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c index e05549a1bd25..f79b05fa5d29 100644 --- a/arch/arm/mach-clps711x/autcpu12.c +++ b/arch/arm/mach-clps711x/autcpu12.c @@ -37,6 +37,7 @@ extern void clps711x_map_io(void); extern void clps711x_init_irq(void); +extern void clps711x_init_time(void); /* * The on-chip registers are given a size of 1MB so that a section can @@ -65,5 +66,6 @@ MACHINE_START(AUTCPU12, "autronix autcpu12") BOOT_PARAMS(0xc0020000) MAPIO(autcpu12_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clp711x_init_time) MACHINE_END diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c index d51668d267fa..3da47264430f 100644 --- a/arch/arm/mach-clps711x/cdb89712.c +++ b/arch/arm/mach-clps711x/cdb89712.c @@ -34,6 +34,7 @@ extern void clps711x_init_irq(void); extern void clps711x_map_io(void); +extern void clps711x-init_time(void); /* * Map the CS89712 Ethernet port. That should be moved to the @@ -55,6 +56,7 @@ MACHINE_START(CDB89712, "Cirrus-CDB89712") BOOT_PARAMS(0xc0000100) MAPIO(cdb89712_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clps711x_init_time) MACHINE_END static int cdb89712_hw_init(void) diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c index e9ef76e18544..44d4e5b8d04b 100644 --- a/arch/arm/mach-clps711x/ceiva.c +++ b/arch/arm/mach-clps711x/ceiva.c @@ -35,6 +35,7 @@ #include <asm/mach/map.h> extern void clps711x_init_irq(void); +extern void clps711x_init_time(void); static struct map_desc ceiva_io_desc[] __initdata = { /* virtual, physical, length, type */ @@ -58,4 +59,5 @@ MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame") BOOT_PARAMS(0xc0000100) MAPIO(ceiva_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clps711x_init_time) MACHINE_END diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c index f74f43583c9a..14fb9788cdd1 100644 --- a/arch/arm/mach-clps711x/clep7312.c +++ b/arch/arm/mach-clps711x/clep7312.c @@ -25,6 +25,7 @@ extern void clps711x_init_irq(void); extern void clps711x_map_io(void); +extern void clps711x_init_time(void); static void __init fixup_clep7312(struct machine_desc *desc, struct tag *tags, @@ -44,5 +45,6 @@ MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") FIXUP(fixup_clep7312) MAPIO(clps711x_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clps711x_init_time) MACHINE_END diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c index 1402447a8ad5..11aa05c24924 100644 --- a/arch/arm/mach-clps711x/edb7211-arch.c +++ b/arch/arm/mach-clps711x/edb7211-arch.c @@ -27,6 +27,7 @@ extern void clps711x_init_irq(void); extern void edb7211_map_io(void); +extern void clps711x_init_time(void); static void __init fixup_edb7211(struct machine_desc *desc, struct tag *tags, @@ -56,4 +57,5 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") FIXUP(fixup_edb7211) MAPIO(edb7211_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clps711x_init_time) MACHINE_END diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index 268e42baa66a..7a4ba27df7b8 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -33,6 +33,7 @@ extern void clps711x_map_io(void); extern void clps711x_init_irq(void); +extern void clps711x_init_time(void); struct meminfo memmap = { .nr_banks = 1, @@ -82,4 +83,5 @@ MACHINE_START(FORTUNET, "ARM-FortuNet") FIXUP(fortunet_fixup) MAPIO(clps711x_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clps711x_init_time) MACHINE_END diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c index b99cccfb773b..eb75ae6678ef 100644 --- a/arch/arm/mach-clps711x/p720t.c +++ b/arch/arm/mach-clps711x/p720t.c @@ -36,6 +36,7 @@ extern void clps711x_init_irq(void); extern void clps711x_map_io(void); +extern void clps711x_init_time(void); /* * Map the P720T system PLD. It occupies two address spaces: @@ -86,6 +87,7 @@ MACHINE_START(P720T, "ARM-Prospector720T") FIXUP(fixup_p720t) MAPIO(p720t_map_io) INITIRQ(clps711x_init_irq) + INITTIME(clps711x_init_time) MACHINE_END static int p720t_hw_init(void) diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c index 8a02e18a899a..58da84effd5e 100644 --- a/arch/arm/mach-clps711x/time.c +++ b/arch/arm/mach-clps711x/time.c @@ -18,12 +18,17 @@ */ #include <linux/timex.h> #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/sched.h> #include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/leds.h> #include <asm/io.h> #include <asm/hardware/clps7111.h> -extern unsigned long (*gettimeoffset)(void); +#include <asm/mach/time.h> + /* * gettimeoffset() returns time since last timer tick, in usecs. @@ -38,19 +43,36 @@ static unsigned long clps711x_gettimeoffset(void) return (hwticks * (tick_nsec / 1000)) / LATCH; } -void __init clps711x_setup_timer(void) +/* + * IRQ handler for the timer + */ +static irqreturn_t +p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + timer_tick(regs); + return IRQ_HANDLED; +} + +static struct irqaction clps711x_timer_irq = { + .name = "CLPS711x Timer Tick", + .flags = SA_INTERRUPT, + .handler = p720t_timer_interrupt +}; + +void __init clps711x_init_time(void) { struct timespec tv; unsigned int syscon; - gettimeoffset = clps711x_gettimeoffset; - syscon = clps_readl(SYSCON1); syscon |= SYSCON1_TC2S | SYSCON1_TC2M; clps_writel(syscon, SYSCON1); clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */ + setup_irq(IRQ_TC2OI, &clps711x_timer_irq); + gettimeoffset = clps711x_gettimeoffset; + tv.tv_nsec = 0; tv.tv_sec = clps_readl(RTCDR); do_settimeofday(&tv); diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index 628264bf50bc..ee1a3192ad7b 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c @@ -10,12 +10,13 @@ #include <linux/types.h> #include <linux/interrupt.h> #include <linux/list.h> -#include <linux/timer.h> +#include <linux/sched.h> #include <linux/init.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> +#include <asm/mach/time.h> #include <asm/hardware.h> #include <asm/hardware/iomd.h> @@ -265,10 +266,47 @@ static void __init clps7500_map_io(void) iotable_init(cl7500_io_desc, ARRAY_SIZE(cl7500_io_desc)); } +extern void ioctime_init(void); + +static irqreturn_t +clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + timer_tick(regs); + + /* Why not using do_leds interface?? */ + { + /* Twinkle the lights. */ + static int count, state = 0xff00; + if (count-- == 0) { + state ^= 0x100; + count = 25; + *((volatile unsigned int *)LED_ADDRESS) = state; + } + } + return IRQ_HANDLED; +} + +static struct irqaction clps7500_timer_irq = { + .name = "CLPS7500 Timer Tick", + .flags = SA_INTERRUPT, + .handler = clps7500_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +void __init clps7500_init_time(void) +{ + ioctime_init(); + + setup_irq(IRQ_TIMER, &clps7500_timer_irq); +} + MACHINE_START(CLPS7500, "CL-PS7500") MAINTAINER("Philip Blundell") BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) MAPIO(clps7500_map_io) INITIRQ(clps7500_init_irq) + INITTIME(clps7500_init_time) MACHINE_END diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 5c14e04eae1b..6f20b86a69c4 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -26,6 +26,8 @@ #include <asm/mach/irq.h> #include <asm/mach/map.h> +#include <asm/mach/time.h> + #define IRQ_MASK 0xfe000000 /* read */ #define IRQ_MSET 0xfe000000 /* write */ #define IRQ_STAT 0xff000000 /* read */ @@ -89,6 +91,103 @@ static void __init ebsa110_map_io(void) iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc)); } + +#define PIT_CTRL (PIT_BASE + 0x0d) +#define PIT_T2 (PIT_BASE + 0x09) +#define PIT_T1 (PIT_BASE + 0x05) +#define PIT_T0 (PIT_BASE + 0x01) + +/* + * This is the rate at which your MCLK signal toggles (in Hz) + * This was measured on a 10 digit frequency counter sampling + * over 1 second. + */ +#define MCLK 47894000 + +/* + * This is the rate at which the PIT timers get clocked + */ +#define CLKBY7 (MCLK / 7) + +/* + * This is the counter value. We tick at 200Hz on this platform. + */ +#define COUNT ((CLKBY7 + (HZ / 2)) / HZ) + +/* + * Get the time offset from the system PIT. Note that if we have missed an + * interrupt, then the PIT counter will roll over (ie, be negative). + * This actually works out to be convenient. + */ +static unsigned long ebsa110_gettimeoffset(void) +{ + unsigned long offset, count; + + __raw_writeb(0x40, PIT_CTRL); + count = __raw_readb(PIT_T1); + count |= __raw_readb(PIT_T1) << 8; + + /* + * If count > COUNT, make the number negative. + */ + if (count > COUNT) + count |= 0xffff0000; + + offset = COUNT; + offset -= count; + + /* + * `offset' is in units of timer counts. Convert + * offset to units of microseconds. + */ + offset = offset * (1000000 / HZ) / COUNT; + + return offset; +} + +static irqreturn_t +ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + u32 count; + + /* latch and read timer 1 */ + __raw_writeb(0x40, PIT_CTRL); + count = __raw_readb(PIT_T1); + count |= __raw_readb(PIT_T1) << 8; + + count += COUNT; + + __raw_writeb(count & 0xff, PIT_T1); + __raw_writeb(count >> 8, PIT_T1); + + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction ebsa110_timer_irq = { + .name = "EBSA110 Timer Tick", + .flags = SA_INTERRUPT, + .handler = ebsa110_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +void __init ebsa110_time_init(void) +{ + /* + * Timer 1, mode 2, LSB/MSB + */ + __raw_writeb(0x70, PIT_CTRL); + __raw_writeb(COUNT & 0xff, PIT_T1); + __raw_writeb(COUNT >> 8, PIT_T1); + + gettimeoffset = ebsa110_gettimeoffset; + + setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq); +} + MACHINE_START(EBSA110, "EBSA110") MAINTAINER("Russell King") BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000) @@ -98,4 +197,5 @@ MACHINE_START(EBSA110, "EBSA110") SOFT_REBOOT MAPIO(ebsa110_map_io) INITIRQ(ebsa110_init_irq) + INITTIME(ebsa110_init_time) MACHINE_END diff --git a/include/asm-arm/arch-ebsa110/time.h b/arch/arm/mach-ebsa110/time.c index c482e372b012..c482e372b012 100644 --- a/include/asm-arm/arch-ebsa110/time.h +++ b/arch/arm/mach-ebsa110/time.c diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c index 71c2257dfd50..ae9f7c864b45 100644 --- a/arch/arm/mach-epxa10db/arch.c +++ b/arch/arm/mach-epxa10db/arch.c @@ -29,10 +29,13 @@ extern void epxa10db_map_io(void); extern void epxa10db_init_irq(void); +extern void epxa10db_init_time(void); MACHINE_START(CAMELOT, "Altera Epxa10db") MAINTAINER("Altera Corporation") BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000) MAPIO(epxa10db_map_io) INITIRQ(epxa10db_init_irq) + INITTIME(epxa10db_init_time) MACHINE_END + diff --git a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c index 0c8b9cf7c7b7..7d72a433dad7 100644 --- a/arch/arm/mach-epxa10db/time.c +++ b/arch/arm/mach-epxa10db/time.c @@ -10,11 +10,17 @@ */ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/sched.h> #include <asm/hardware.h> +#include <asm/system.h> +#include <asm/leds.h> +#include <asm/mach/time.h> -extern int (*set_rtc)(void); +#define TIMER00_TYPE (volatile unsigned int*) +#include <asm/arch/timer00.h> static int epxa10db_set_rtc(void) { @@ -29,3 +35,39 @@ static int epxa10db_rtc_init(void) } __initcall(epxa10db_rtc_init); + + +/* + * IRQ handler for the timer + */ +static irqreturn_t +epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + + // ...clear the interrupt + *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK; + + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction epxa10db_timer_irq = { + .name = "Excalibur Timer Tick", + .flags = SA_INTERRUPT, + .handler = epxa10db_timer_interrupt +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init epxa10db_init_time(void) +{ + /* Start the timer */ + *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200); + *TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1; + *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK; + + setup_irq(IRQ_TIMER0, &epxa10db_timer_irq); +} + diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile index d011b2df2dbe..e0a2890522cd 100644 --- a/arch/arm/mach-footbridge/Makefile +++ b/arch/arm/mach-footbridge/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y := arch.o dc21285.o dma.o irq.o isa-irq.o mm.o +obj-y := arch.o dc21285.o dma.o irq.o isa-irq.o mm.o time.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-footbridge/arch.c b/arch/arm/mach-footbridge/arch.c index 91e34a8440ef..76119883661e 100644 --- a/arch/arm/mach-footbridge/arch.c +++ b/arch/arm/mach-footbridge/arch.c @@ -22,6 +22,7 @@ extern void footbridge_map_io(void); extern void footbridge_init_irq(void); +extern void footbridge_init_time(void); unsigned int mem_fclk_21285 = 50000000; @@ -43,6 +44,7 @@ MACHINE_START(EBSA285, "EBSA285") VIDEO(0x000a0000, 0x000bffff) MAPIO(footbridge_map_io) INITIRQ(footbridge_init_irq) + INITTIME(footbridge_init_time) MACHINE_END #endif @@ -78,6 +80,7 @@ MACHINE_START(NETWINDER, "Rebel-NetWinder") FIXUP(fixup_netwinder) MAPIO(footbridge_map_io) INITIRQ(footbridge_init_irq) + INITTIME(footbridge_init_time) MACHINE_END #endif @@ -103,6 +106,7 @@ MACHINE_START(CATS, "Chalice-CATS") FIXUP(fixup_cats) MAPIO(footbridge_map_io) INITIRQ(footbridge_init_irq) + INITTIME(footbridge_init_time) MACHINE_END #endif @@ -129,6 +133,7 @@ MACHINE_START(CO285, "co-EBSA285") FIXUP(fixup_coebsa285) MAPIO(footbridge_map_io) INITIRQ(footbridge_init_irq) + INITTIME(footbridge_init_time) MACHINE_END #endif @@ -139,5 +144,6 @@ MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer") BOOT_PARAMS(0x00000100) MAPIO(footbridge_map_io) INITIRQ(footbridge_init_irq) + INITTIME(footbridge_init_time) MACHINE_END #endif diff --git a/include/asm-arm/arch-ebsa285/time.h b/arch/arm/mach-footbridge/time.c index f651eeb655be..d4b9c9f87fff 100644 --- a/include/asm-arm/arch-ebsa285/time.h +++ b/arch/arm/mach-footbridge/time.c @@ -17,12 +17,23 @@ #define RTC_PORT(x) (rtc_base+(x)) #define RTC_ALWAYS_BCD 0 +#include <linux/timex.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/sched.h> #include <linux/mc146818rtc.h> #include <linux/bcd.h> #include <asm/hardware/dec21285.h> + +#include <asm/hardware.h> +#include <asm/irq.h> #include <asm/leds.h> #include <asm/mach-types.h> +#include <asm/io.h> +#include <asm/hardware/clps7111.h> + +#include <asm/mach/time.h> static int rtc_base; @@ -72,12 +83,7 @@ static unsigned long isa_gettimeoffset(void) static irqreturn_t isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - if (machine_is_netwinder()) - do_leds(); - - do_timer(regs); - do_set_rtc(); - do_profile(regs); + timer_tick(regs); return IRQ_HANDLED; } @@ -195,22 +201,20 @@ timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) { *CSR_TIMER1_CLR = 0; - /* Do the LEDs things */ - do_leds(); - do_timer(regs); - do_set_rtc(); - do_profile(regs); + timer_tick(regs); return IRQ_HANDLED; } +static struct irqaction footbridge_timer_irq = { + .flags = SA_INTERRUPT +}; + /* * Set up timer interrupt. */ -void __init time_init(void) +void __init footbridge_init_time(void) { - int irq; - if (machine_is_co285() || machine_is_personal_server()) /* @@ -270,8 +274,11 @@ void __init time_init(void) *CSR_TIMER1_LOAD = timer1_latch; *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; - timer_irq.handler = timer1_interrupt; - irq = IRQ_TIMER1; + footbridge_timer_irq.name = "Timer1 Timer Tick"; + footbrdige_timer_irq.handler = timer1_interrupt; + + setup_irq(IRQ_TIMER1, &footbridge_timer_irq); + } else { /* enable PIT timer */ /* set for periodic (4) and LSB/MSB write (0x30) */ @@ -280,8 +287,10 @@ void __init time_init(void) outb((mSEC_10_from_14/6) >> 8, 0x40); gettimeoffset = isa_gettimeoffset; - timer_irq.handler = isa_timer_interrupt; - irq = IRQ_ISA_TIMER; + + footbridge_timer_irq.name = "ISA Timer Tick"; + footbrdige_timer_irq.handler = isa_timer_interrupt; + + setup_irq(IRQ_ISA, &footbridge_timer_irq); } - setup_irq(irq, &timer_irq); } diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 1d59766652d3..4fee881855f1 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -281,11 +281,17 @@ static void __init ap_init(void) } } +static void ap_time_init(void) +{ + integrator_time_init(1000000 * TICKS_PER_uSEC / HZ, 0); +} + MACHINE_START(INTEGRATOR, "ARM-Integrator") MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") BOOT_MEM(0x00000000, 0x16000000, 0xf1600000) BOOT_PARAMS(0x00000100) MAPIO(ap_map_io) INITIRQ(ap_init_irq) + INITTIME(ap_time_init) INIT_MACHINE(ap_init) MACHINE_END diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index f63e45cbe8fa..aa29c76aacc0 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -249,7 +249,7 @@ static struct clk cp_clcd_clk = { static struct clk cp_mmci_clk = { .name = "MCLK", - .rate = 33000000, + .rate = 14745600, }; /* @@ -351,7 +351,7 @@ static unsigned int mmc_status(struct device *dev) } static struct mmc_platform_data mmc_data = { - .mclk = 33000000, + .mclk = 14745600, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .status = mmc_status, }; @@ -419,11 +419,17 @@ static void __init intcp_init(void) } } +static void __init intcp_init_time(void) +{ + integrator_time_init(1000000 / HZ, TIMER_CTRL_IE); +} + MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") BOOT_MEM(0x00000000, 0x16000000, 0xf1600000) BOOT_PARAMS(0x00000100) MAPIO(intcp_map_io) INITIRQ(intcp_init_irq) + INITTIME(intcp_init_time) INIT_MACHINE(intcp_init) MACHINE_END diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c index 39606096fbd6..e12bcf814d95 100644 --- a/arch/arm/mach-integrator/time.c +++ b/arch/arm/mach-integrator/time.c @@ -10,9 +10,16 @@ #include <linux/kernel.h> #include <linux/time.h> #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/sched.h> #include <asm/hardware.h> #include <asm/io.h> +#include <asm/system.h> +#include <asm/leds.h> +#include <asm/mach-types.h> + +#include <asm/mach/time.h> #define RTC_DR (IO_ADDRESS(INTEGRATOR_RTC_BASE) + 0) #define RTC_MR (IO_ADDRESS(INTEGRATOR_RTC_BASE) + 4) @@ -44,3 +51,140 @@ static int integrator_rtc_init(void) } __initcall(integrator_rtc_init); + + +/* + * Where is the timer (VA)? + */ +#define TIMER0_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000000) +#define TIMER1_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000100) +#define TIMER2_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000200) +#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) + +/* + * How long is the timer interval? + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) +#if TIMER_INTERVAL >= 0x100000 +#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) +#elif TIMER_INTERVAL >= 0x10000 +#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) +#else +#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) +#endif + +#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ + +/* + * What does it look like? + */ +typedef struct TimerStruct { + unsigned long TimerLoad; + unsigned long TimerValue; + unsigned long TimerControl; + unsigned long TimerClear; +} TimerStruct_t; + +extern unsigned long (*gettimeoffset)(void); + +static unsigned long timer_reload; + +/* + * Returns number of ms since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long integrator_gettimeoffset(void) +{ + volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE; + unsigned long ticks1, ticks2, status; + + /* + * Get the current number of ticks. Note that there is a race + * condition between us reading the timer and checking for + * an interrupt. We get around this by ensuring that the + * counter has not reloaded between our two reads. + */ + ticks2 = timer1->TimerValue & 0xffff; + do { + ticks1 = ticks2; + status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS); + ticks2 = timer1->TimerValue & 0xffff; + } while (ticks2 > ticks1); + + /* + * Number of ticks since last interrupt. + */ + ticks1 = timer_reload - ticks2; + + /* + * Interrupt pending? If so, we've reloaded once already. + */ + if (status & (1 << IRQ_TIMERINT1)) + ticks1 += timer_reload; + + /* + * Convert the ticks to usecs + */ + return TICKS2USECS(ticks1); +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t +integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; + + // ...clear the interrupt + timer1->TimerClear = 1; + + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction integrator_timer_irq = { + .name = "Integrator Timer Tick", + .flags = SA_INTERRUPT, + .handler = integrator_timer_interrupt +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init integrator_time_init(unsigned long reload, unsigned int ctrl) +{ + volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; + volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; + volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE; + unsigned int timer_ctrl = 0x80 | 0x40; /* periodic */ + + timer_reload = reload; + timer_ctrl |= ctrl; + + if (timer_reload > 0x100000) { + timer_reload >>= 8; + timer_ctrl |= 0x08; /* /256 */ + } else if (timer_reload > 0x010000) { + timer_reload >>= 4; + timer_ctrl |= 0x04; /* /16 */ + } + + /* + * Initialise to a known state (all timers off) + */ + timer0->TimerControl = 0; + timer1->TimerControl = 0; + timer2->TimerControl = 0; + + timer1->TimerLoad = timer_reload; + timer1->TimerValue = timer_reload; + timer1->TimerControl = timer_ctrl; + + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); + gettimeoffset = integrator_gettimeoffset; +} diff --git a/arch/arm/mach-iop3xx/arch.c b/arch/arm/mach-iop3xx/arch.c index eb3bab2db9c4..3df5e454c772 100644 --- a/arch/arm/mach-iop3xx/arch.c +++ b/arch/arm/mach-iop3xx/arch.c @@ -29,6 +29,7 @@ extern void iq80310_init_irq(void); #ifdef CONFIG_ARCH_IQ80321 extern void iq80321_map_io(void); extern void iop321_init_irq(void); +extern void iop321_init_time(void); #endif #ifdef CONFIG_ARCH_IQ80310 @@ -67,6 +68,7 @@ MACHINE_START(IQ80321, "Intel IQ80321") FIXUP(fixup_iop321) MAPIO(iq80321_map_io) INITIRQ(iop321_init_irq) + INITTIME(iop321_init_time) MACHINE_END #else diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c index a10a9b9533d1..be36c70690b1 100644 --- a/arch/arm/mach-iop3xx/iop321-time.c +++ b/arch/arm/mach-iop3xx/iop321-time.c @@ -23,7 +23,9 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> + #include <asm/mach/irq.h> +#include <asm/mach/time.h> static unsigned long iop321_gettimeoffset(void) { @@ -61,27 +63,26 @@ iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr)); - do_timer(regs); + timer_tick(regs); return IRQ_HANDLED; } -extern unsigned long (*gettimeoffset)(void); - -static struct irqaction timer_irq = { - .name = "timer", +static struct irqaction iop321_timer_irq = { + .name = "IOP321 Timer Tick", .handler = iop321_timer_interrupt, + .flags = SA_INTERRUPT }; extern int setup_arm_irq(int, struct irqaction*); -void __init time_init(void) +void __init iop321_init_time(void) { u32 timer_ctl; u32 latch = LATCH; gettimeoffset = iop321_gettimeoffset; - setup_irq(IRQ_IOP321_TIMER0, &timer_irq); + setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq); timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD | IOP321_TMR_RATIO_1_1; diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index f0166508d5bb..a4edbe0eb909 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -36,6 +36,7 @@ #include <asm/mach/map.h> #include <asm/mach/irq.h> +#include <asm/mach/time.h> /************************************************************************* @@ -227,24 +228,22 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs * Catch up with the real idea of time */ do { - do_timer(regs); + timer_tick(regs); last_jiffy_time += LATCH; } while((*IXP4XX_OSTS - last_jiffy_time) > LATCH); return IRQ_HANDLED; } -extern unsigned long (*gettimeoffset)(void); - -static struct irqaction timer_irq = { - .name = "IXP4xx Timer Tick", - .flags = SA_INTERRUPT +static struct irqaction ixp4xx_timer_irq = { + .name = "IXP4xx Timer Tick", + .flags = SA_INTERRUPT, + .handler = ixp4xx_timer_interrupt }; -void __init time_init(void) +void __init ixp4xx_init_time(void) { gettimeoffset = ixp4xx_gettimeoffset; - timer_irq.handler = ixp4xx_timer_interrupt; /* Clear Pending Interrupt by writing '1' to it */ *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; @@ -257,7 +256,7 @@ void __init time_init(void) last_jiffy_time = 0; /* Connect the interrupt handler and enable the interrupt */ - setup_irq(IRQ_IXP4XX_TIMER1, &timer_irq); + setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); } diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index bc6e0d0427a2..3d616bc6aff4 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -84,6 +84,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering IXP4XX Coyote Development Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(coyote_map_io) INITIRQ(ixp4xx_init_irq) + INITTIME(ixp4xx_init_time) BOOT_PARAMS(0x0100) INIT_MACHINE(coyote_init) MACHINE_END diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 160117c67764..ec289c866ae7 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -113,6 +113,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(ixdp425_map_io) INITIRQ(ixp4xx_init_irq) + INITTIME(ixp4xx_init_time) BOOT_PARAMS(0x0100) INIT_MACHINE(ixdp425_init) MACHINE_END @@ -123,6 +124,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(ixdp425_map_io) INITIRQ(ixp4xx_init_irq) + INITTIME(ixp4xx_init_time) BOOT_PARAMS(0x0100) INIT_MACHINE(ixdp425_init) MACHINE_END @@ -140,6 +142,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(ixdp425_map_io) INITIRQ(ixp4xx_init_irq) + INITTIME(ixp4xx_init_time) BOOT_PARAMS(0x0100) INIT_MACHINE(ixdp425_init) MACHINE_END diff --git a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c index b0603205d070..ee092b1771cc 100644 --- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c +++ b/arch/arm/mach-ixp4xx/prpmc1100-setup.c @@ -84,6 +84,7 @@ MACHINE_START(PRPMC1100, "Motorola PrPMC1100") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(prpmc1100_map_io) INITIRQ(ixp4xx_init_irq) + INITTIME(ixp4xx_init_time) BOOT_PARAMS(0x0100) INIT_MACHINE(prpmc1100_init) MACHINE_END diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile index db3be5a23a8a..6b361f788a22 100644 --- a/arch/arm/mach-lh7a40x/Makefile +++ b/arch/arm/mach-lh7a40x/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y := fiq.o +obj-y := fiq.o time.o # generic.o obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o ide-lpd7a40x.o irq-lh7a400.o diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c index 73d8b6b56e4c..6fa2a981ee80 100644 --- a/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -25,6 +25,7 @@ /* This function calls the board specific IRQ initialization function. */ extern void lh7a400_init_irq (void); +extern void lh7a40x_init_time (void); static struct map_desc kev7a400_io_desc[] __initdata = { { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE }, @@ -108,4 +109,5 @@ MACHINE_START (KEV7A400, "Sharp KEV7a400") BOOT_PARAMS (0xc0000100) MAPIO (kev7a400_map_io) INITIRQ (lh7a400_init_irq) + INITTIME (lh7a40x_init_time) MACHINE_END diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 75dba98360c0..33eb4b8dd358 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -280,6 +280,7 @@ MACHINE_END #ifdef CONFIG_MACH_LPD7A404 extern void lh7a404_init_irq (void); +extern void lh7a40x_init_time (void); MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10") MAINTAINER ("Marc Singer") @@ -287,6 +288,7 @@ MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10") BOOT_PARAMS (0xc0000100) MAPIO (lpd7a400_map_io) INITIRQ (lh7a404_init_irq) + INITTIME (lh7a40x_init_time) INIT_MACHINE (lpd7a40x_init) MACHINE_END diff --git a/include/asm-arm/arch-lh7a40x/time.h b/arch/arm/mach-lh7a40x/time.c index 5f1cf4f9b2c7..61ada24c78a7 100644 --- a/include/asm-arm/arch-lh7a40x/time.h +++ b/arch/arm/mach-lh7a40x/time.c @@ -1,4 +1,5 @@ -/* include/asm-arm/arch-lh7a40x/time.h +/* + * arch/arm/mach-lh7a40x/time.c * * Copyright (C) 2004 Logic Product Development * @@ -7,6 +8,18 @@ * version 2 as published by the Free Software Foundation. * */ +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/time.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/leds.h> + +#include <asm/mach/time.h> #if HZ < 100 # define TIMER_CONTROL TIMER_CONTROL1 @@ -28,24 +41,25 @@ static irqreturn_t lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { TIMER_EOI = 0; - do_profile (regs); - do_leds(); - do_set_rtc(); - do_timer (regs); + timer_tick(regs); return IRQ_HANDLED; } -void __init time_init(void) +static struct irqaction lh7a40x_timer_irq = { + .name = "LHA740x Timer Tick", + .flags = SA_INTERRUPT, + .handler = lh7a40x_timer_interrupt +}; + +void __init lh7a40x_init_time(void) { /* Stop/disable all timers */ TIMER_CONTROL1 = 0; TIMER_CONTROL2 = 0; TIMER_CONTROL3 = 0; - timer_irq.handler = lh7a40x_timer_interrupt; - timer_irq.flags |= SA_INTERRUPT; - setup_irq (TIMER_IRQ, &timer_irq); + setup_irq (TIMER_IRQ, &lh7a40x_timer_irq); TIMER_LOAD = TIMER_CONSTANT; TIMER_CONTROL = TIMER_MODE; diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 272535091bc4..5fcb1e5c7627 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o +obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o time.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c index e0b09f86ae92..447046b24a08 100644 --- a/arch/arm/mach-omap/board-generic.c +++ b/arch/arm/mach-omap/board-generic.c @@ -65,6 +65,11 @@ static void __init omap_generic_map_io(void) omap_map_io(); } +static void __init omap_generic_init_time(void) +{ + omap_init_time(); +} + MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710") MAINTAINER("Tony Lindgren <tony@atomide.com>") BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000) @@ -72,4 +77,6 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710") MAPIO(omap_generic_map_io) INITIRQ(omap_generic_init_irq) INIT_MACHINE(omap_generic_init) + INITTIME(omap_generic_init_time) MACHINE_END + diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c index c65f38f58bb8..6ef4d8dcf903 100644 --- a/arch/arm/mach-omap/board-innovator.c +++ b/arch/arm/mach-omap/board-innovator.c @@ -156,5 +156,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") BOOT_PARAMS(0x10000100) MAPIO(innovator_map_io) INITIRQ(innovator_init_irq) + INITTIME(omap_init_time) INIT_MACHINE(innovator_init) MACHINE_END diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c index 8044dd190efd..16ecd6be5a60 100644 --- a/arch/arm/mach-omap/board-osk.c +++ b/arch/arm/mach-omap/board-osk.c @@ -94,5 +94,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK") BOOT_PARAMS(0x10000100) MAPIO(osk_map_io) INITIRQ(osk_init_irq) + INITTIME(omap_init_time) INIT_MACHINE(osk_init) MACHINE_END diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c index e938ea4b647e..8015d10fc75e 100644 --- a/arch/arm/mach-omap/board-perseus2.c +++ b/arch/arm/mach-omap/board-perseus2.c @@ -111,5 +111,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") BOOT_PARAMS(0x10000100) MAPIO(omap_perseus2_map_io) INITIRQ(omap_perseus2_init_irq) + INITTIME(omap_init_time) INIT_MACHINE(omap_perseus2_init) MACHINE_END diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h index 1cc559dd2f81..96dcb3c53973 100644 --- a/arch/arm/mach-omap/common.h +++ b/arch/arm/mach-omap/common.h @@ -28,6 +28,7 @@ #define __ARCH_ARM_MACH_OMAP_COMMON_H extern void omap_map_io(void); +extern void omap_init_time(void); #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ diff --git a/include/asm-arm/arch-omap/time.h b/arch/arm/mach-omap/time.c index 85d481219824..d62e22614394 100644 --- a/include/asm-arm/arch-omap/time.h +++ b/arch/arm/mach-omap/time.c @@ -1,7 +1,7 @@ /* - * linux/include/asm-arm/arch-omap/time.h + * arch/arm/mach-omap/time.c * - * 32kHz timer definition + * OMAP Timer Tick * * Copyright (C) 2000 RidgeRun, Inc. * Author: Greg Lonnon <glonnon@ridgerun.com> @@ -26,8 +26,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(__ASM_ARCH_OMAP_TIME_H) -#define __ASM_ARCH_OMAP_TIME_H #include <linux/config.h> #include <linux/delay.h> @@ -37,6 +35,7 @@ #include <asm/leds.h> #include <asm/irq.h> #include <asm/mach/irq.h> +#include <asm/mach/time.h> #include <asm/arch/clocks.h> #ifndef __instrument @@ -162,14 +161,14 @@ unsigned long __noinstrument machinecycles_to_usecs(unsigned long mputicks) */ static unsigned long systimer_mark; -static unsigned long omap1510_gettimeoffset(void) +static unsigned long omap_gettimeoffset(void) { /* Return elapsed usecs since last system timer ISR */ return machinecycles_to_usecs(do_getmachinecycles() - systimer_mark); } static irqreturn_t -omap1510_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned long now, ilatency; @@ -184,29 +183,30 @@ omap1510_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ilatency = MPUTICKS_PER_SEC / 100 - read_mputimer2(); systimer_mark = now - ilatency; - do_leds(); - do_timer(regs); - do_profile(regs); + timer_tick(regs); return IRQ_HANDLED; } -void __init time_init(void) +static struct irqaction omap_timer_irq = { + .name = "OMAP Timer Tick", + .flags = SA_INTERRUPT, + .handler = omap_timer_interrupt +}; + +void __init omap_init_time(void) { /* Since we don't call request_irq, we must init the structure */ - gettimeoffset = omap1510_gettimeoffset; + gettimeoffset = omap_gettimeoffset; - timer_irq.handler = omap1510_timer_interrupt; - timer_irq.flags = SA_INTERRUPT; #ifdef OMAP1510_USE_32KHZ_TIMER timer32k_write(TIMER32k_CR, 0x0); timer32k_write(TIMER32k_TVR,TIMER32k_PERIOD); - setup_irq(INT_OS_32kHz_TIMER, &timer_irq); + setup_irq(INT_OS_32kHz_TIMER, &omap_timer_irq); start_timer32k(); #else - setup_irq(INT_TIMER2, &timer_irq); + setup_irq(INT_TIMER2, &omap_timer_irq); start_mputimer2(MPUTICKS_PER_SEC / 100 - 1); #endif } -#endif diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index cc33a476796b..23c51e388a91 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -3,7 +3,7 @@ # # Common support (must be linked before board specific support) -obj-y += generic.o irq.o dma.o +obj-y += generic.o irq.o dma.o time.o obj-$(CONFIG_PXA25x) += pxa25x.o obj-$(CONFIG_PXA27x) += pxa27x.o diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 20b776ff92d2..981f7b9750f1 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -198,10 +198,26 @@ static struct platform_device pxafb_device = { .resource = pxafb_resources, }; +static struct platform_device ffuart_device = { + .name = "pxa2xx-uart", + .id = 0, +}; +static struct platform_device btuart_device = { + .name = "pxa2xx-uart", + .id = 1, +}; +static struct platform_device stuart_device = { + .name = "pxa2xx-uart", + .id = 2, +}; + static struct platform_device *devices[] __initdata = { &pxamci_device, &udc_device, &pxafb_device, + &ffuart_device, + &btuart_device, + &stuart_device, }; static int __init pxa_init(void) diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 6b33fb03ce42..0534d175617a 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -11,6 +11,7 @@ extern void __init pxa_map_io(void); extern void __init pxa_init_irq(void); +extern void __init pxa_init_time(void); #define SET_BANK(__nr,__start,__size) \ mi->bank[__nr].start = (__start), \ diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 706858ea2490..db53cd571cd0 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -118,5 +118,6 @@ MACHINE_START(PXA_IDP, "Accelent Xscale IDP") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(idp_map_io) INITIRQ(idp_init_irq) + INITTIME(pxa_init_time) INIT_MACHINE(idp_init) MACHINE_END diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 023c5e9f316f..ce8666a7a79e 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -220,5 +220,6 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(lubbock_map_io) INITIRQ(lubbock_init_irq) + INITTIME(pxa_init_time) INIT_MACHINE(lubbock_init) MACHINE_END diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 663c1eef8a0a..ac998c44d577 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -137,5 +137,6 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(mainstone_map_io) INITIRQ(mainstone_init_irq) + INITTIME(pxa_init_time) INIT_MACHINE(mainstone_init) MACHINE_END diff --git a/include/asm-arm/arch-pxa/time.h b/arch/arm/mach-pxa/time.c index bc9437a8c38d..7e89235632f8 100644 --- a/include/asm-arm/arch-pxa/time.h +++ b/arch/arm/mach-pxa/time.c @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/arch-pxa/time.h + * arch/arm/mach-pxa/time.c * * Author: Nicolas Pitre * Created: Jun 15, 2001 @@ -10,6 +10,24 @@ * published by the Free Software Foundation. */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/time.h> +#include <linux/signal.h> +#include <linux/errno.h> +#include <linux/sched.h> + +#include <asm/system.h> +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/leds.h> +#include <asm/irq.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> + static inline unsigned long pxa_get_rtc_time(void) { @@ -56,8 +74,6 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int next_match; - do_profile(regs); - /* Loop until we get ahead of the free running timer. * This ensures an exact clock tick count and time accuracy. * IRQs are disabled inside the loop to ensure coherence between @@ -74,9 +90,7 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * exactly one tick period which should be a pretty rare event. */ do { - do_leds(); - do_set_rtc(); - do_timer(regs); + timer_tick(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ next_match = (OSMR0 += LATCH); } while( (signed long)(next_match - OSCR) <= 8 ); @@ -84,7 +98,13 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -void __init time_init(void) +static struct irqaction pxa_timer_irq = { + .name = "PXA Timer Tick", + .flags = SA_INTERRUPT, + .handler = pxa_timer_interrupt +}; + +void __init pxa_init_time(void) { struct timespec tv; @@ -95,10 +115,9 @@ void __init time_init(void) tv.tv_sec = pxa_get_rtc_time(); do_settimeofday(&tv); - timer_irq.handler = pxa_timer_interrupt; OSMR0 = 0; /* set initial match at 0 */ OSSR = 0xf; /* clear status on all timers */ - setup_irq(IRQ_OST0, &timer_irq); + setup_irq(IRQ_OST0, &pxa_timer_irq); OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */ OSCR = 0; /* initialize free-running timer, force first match */ } diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index f45e28116609..d5a1a3af216c 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -14,6 +14,8 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/init.h> +#include <linux/sched.h> +#include <linux/interrupt.h> #include <asm/elf.h> #include <asm/io.h> @@ -25,6 +27,7 @@ #include <asm/mach/map.h> #include <asm/mach/arch.h> +#include <asm/mach/time.h> extern void rpc_init_irq(void); @@ -82,6 +85,31 @@ void __init rpc_map_io(void) elf_hwcap &= ~HWCAP_HALF; } +static irqreturn_t +rpc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction rpc_timer_irq = { + .name = "RiscPC Timer Tick", + .flags = SA_INTERRUPT, + .handler = rpc_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +void __init rpc_init_time(void) +{ + extern void ioctime_init(void); + ioctime_init(); + + setup_irq(IRQ_TIMER, &rpc_timer_irq); +} + MACHINE_START(RISCPC, "Acorn-RiscPC") MAINTAINER("Russell King") BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) @@ -90,4 +118,5 @@ MACHINE_START(RISCPC, "Acorn-RiscPC") DISABLE_PARPORT(1) MAPIO(rpc_map_io) INITIRQ(rpc_init_irq) + INITTIME(rpc_init_time) MACHINE_END diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index d36316999639..d183de782168 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y := s3c2410.o irq.o +obj-y := s3c2410.o irq.o time.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index c1f566f319f5..2268ab3c7c69 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -185,10 +185,16 @@ void __init bast_init_irq(void) } +void __init bast_init_time(void) +{ + s3c2410_init_time(); +} + MACHINE_START(BAST, "Simtec-BAST") MAINTAINER("Ben Dooks <ben@simtec.co.uk>") BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(bast_map_io) INITIRQ(bast_init_irq) + INITTIME(bast_init_time) MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index a66b451ec7d0..f3515bcec1b7 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -91,10 +91,16 @@ void __init ipaq_init_irq(void) } +void __init ipaq_init_time(void) +{ + s3c2410_init_time(); +} + MACHINE_START(H1940, "IPAQ-H1940") MAINTAINER("Ben Dooks <ben@fluff.org>") BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(ipaq_map_io) INITIRQ(ipaq_init_irq) + INITTIME(ipaq_init_time) MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 4e0282b12fbb..fb180732b860 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -99,6 +99,11 @@ void __init smdk2410_init_irq(void) s3c2410_init_irq(); } +void __init smdk2410_init_time(void) +{ + s3c2401_init_time(); +} + MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch * to SMDK2410 */ MAINTAINER("Jonas Dietsche") @@ -106,4 +111,5 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(smdk2410_map_io) INITIRQ(smdk2410_init_irq) + INITTIME(smdk2410_init_time) MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 1758422da7bf..856739ba1921 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -155,10 +155,16 @@ void __init vr1000_init_irq(void) } +void __init vr1000_init_time(void) +{ + s3c2401_init_time(); +} + MACHINE_START(VR1000, "Simtec-VR1000") MAINTAINER("Ben Dooks <ben@simtec.co.uk>") BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(vr1000_map_io) INITIRQ(vr1000_init_irq) + INITTIME(vr1000_init_time) MACHINE_END diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h index 80c336caa86d..5ff132081a6f 100644 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ b/arch/arm/mach-s3c2410/s3c2410.h @@ -4,3 +4,5 @@ extern void s3c2410_map_io(struct map_desc *, int count); extern void s3c2410_init_irq(void); +extern s3c2410_init_time(void); + diff --git a/include/asm-arm/arch-s3c2410/time.h b/arch/arm/mach-s3c2410/time.c index 8aab3438a992..62d89d98c423 100644 --- a/include/asm-arm/arch-s3c2410/time.h +++ b/arch/arm/mach-s3c2410/time.c @@ -18,15 +18,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/interrupt.h> #include <asm/system.h> #include <asm/leds.h> #include <asm/mach-types.h> #include <asm/io.h> +#include <asm/irq.h> #include <asm/arch/map.h> #include <asm/arch/regs-timer.h> - -extern unsigned long (*gettimeoffset)(void); +#include <asm/mach/time.h> static unsigned long timer_startval; static unsigned long timer_ticks_usec; @@ -69,25 +74,24 @@ static unsigned long s3c2410_gettimeoffset (void) static irqreturn_t s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - do_leds(); - do_timer(regs); - - do_set_rtc(); - //s3c2410_rtc_check(); - do_profile(regs); + timer_tick(regs); return IRQ_HANDLED; } +static struct irqaction s3c2410_timer_irq = { + .name = "S32410 Timer Tick", + .flags = SA_INTERRUPT, + .handler = s3c2410_timer_interrupt +}; + /* * Set up timer interrupt, and return the current time in seconds. - */ - -/* currently we only use timer4, as it is the only timer which has no + * + * Currently we only use timer4, as it is the only timer which has no * other function that can be exploited externally -*/ - -void __init time_init (void) + */ +void __init s3c2410_init_time (void) { unsigned long tcon; unsigned long tcnt; @@ -95,7 +99,6 @@ void __init time_init (void) unsigned long tcfg0; gettimeoffset = s3c2410_gettimeoffset; - timer_irq.handler = s3c2410_timer_interrupt; tcnt = 0xffff; /* default value for tcnt */ @@ -161,7 +164,7 @@ void __init time_init (void) __raw_writel(tcnt, S3C2410_TCNTB(4)); __raw_writel(tcnt, S3C2410_TCMPB(4)); - setup_irq(IRQ_TIMER4, &timer_irq); + setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); /* start the timer running */ tcon |= S3C2410_TCON_T4START; diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c index d028a87ce2eb..53f990e7d615 100644 --- a/arch/arm/mach-sa1100/adsbitsy.c +++ b/arch/arm/mach-sa1100/adsbitsy.c @@ -147,4 +147,5 @@ MACHINE_START(ADSBITSY, "ADS Bitsy") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(adsbitsy_map_io) INITIRQ(adsbitsy_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index dcd32454e606..e5098cf9c2e9 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -324,5 +324,6 @@ MACHINE_START(ASSABET, "Intel-Assabet") FIXUP(fixup_assabet) MAPIO(assabet_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) INIT_MACHINE(assabet_init) MACHINE_END diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index 71d9e165a3b6..cef71047ccb7 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -245,4 +245,5 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") BOOT_PARAMS(0xc0000100) MAPIO(badge4_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/brutus.c b/arch/arm/mach-sa1100/brutus.c index fdfe024b10fa..925bf0e59fe8 100644 --- a/arch/arm/mach-sa1100/brutus.c +++ b/arch/arm/mach-sa1100/brutus.c @@ -37,4 +37,5 @@ MACHINE_START(BRUTUS, "Intel Brutus (SA1100 eval board)") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(brutus_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 00af122c4819..2c4c05013cc9 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -92,4 +92,5 @@ MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(cerf_map_io) INITIRQ(cerf_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/empeg.c b/arch/arm/mach-sa1100/empeg.c index b1faaa92f930..6ab57cdb0182 100644 --- a/arch/arm/mach-sa1100/empeg.c +++ b/arch/arm/mach-sa1100/empeg.c @@ -35,4 +35,5 @@ MACHINE_START(EMPEG, "empeg MP3 Car Audio Player") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(empeg_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c index 0a40c7831515..370df9f773cf 100644 --- a/arch/arm/mach-sa1100/flexanet.c +++ b/arch/arm/mach-sa1100/flexanet.c @@ -183,5 +183,6 @@ MACHINE_START(FLEXANET, "FlexaNet") BOOT_PARAMS(0xc0000100) MAPIO(flexanet_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c index 5363d02ee7e6..abd27aef72f9 100644 --- a/arch/arm/mach-sa1100/freebird.c +++ b/arch/arm/mach-sa1100/freebird.c @@ -77,4 +77,5 @@ MACHINE_START(FREEBIRD, "Freebird-HPC-1.1") #endif MAPIO(freebird_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 4649fc5c5c4e..04bcfeb3b8a1 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -6,6 +6,7 @@ extern void __init sa1100_map_io(void); extern void __init sa1100_init_irq(void); +extern void __init sa1100_init_time(void); #define SET_BANK(__nr,__start,__size) \ mi->bank[__nr].start = (__start), \ diff --git a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c index eb420d53a93d..2f628adbda2c 100644 --- a/arch/arm/mach-sa1100/graphicsclient.c +++ b/arch/arm/mach-sa1100/graphicsclient.c @@ -198,4 +198,5 @@ MACHINE_START(GRAPHICSCLIENT, "ADS GraphicsClient") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(graphicsclient_map_io) INITIRQ(graphicsclient_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c index 77d84368d7ac..7f1cfd18eaca 100644 --- a/arch/arm/mach-sa1100/graphicsmaster.c +++ b/arch/arm/mach-sa1100/graphicsmaster.c @@ -287,4 +287,5 @@ MACHINE_START(GRAPHICSMASTER, "ADS GraphicsMaster") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(graphicsmaster_map_io) INITIRQ(graphicsmaster_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 9868d4129650..54ab44452401 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -286,6 +286,7 @@ MACHINE_START(H3100, "Compaq iPAQ H3100") BOOT_PARAMS(0xc0000100) MAPIO(h3100_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END #endif /* CONFIG_SA1100_H3100 */ @@ -400,6 +401,7 @@ MACHINE_START(H3600, "Compaq iPAQ H3600") BOOT_PARAMS(0xc0000100) MAPIO(h3600_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END #endif /* CONFIG_SA1100_H3600 */ @@ -783,6 +785,7 @@ MACHINE_START(H3800, "Compaq iPAQ H3800") BOOT_PARAMS(0xc0000100) MAPIO(h3800_map_io) INITIRQ(h3800_init_irq) + INITTIME(sa1100_init_time) MACHINE_END #endif /* CONFIG_SA1100_H3800 */ diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index e79bb441c8fe..e24be9716ba4 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -174,4 +174,5 @@ MACHINE_START(HACKKIT, "HackKit Cpu Board") BOOT_PARAMS(0xc0000100) MAPIO(hackkit_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c index 1ed5f365c950..771b10620249 100644 --- a/arch/arm/mach-sa1100/huw_webpanel.c +++ b/arch/arm/mach-sa1100/huw_webpanel.c @@ -81,4 +81,5 @@ MACHINE_START(HUW_WEBPANEL, "HuW-Webpanel") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(huw_webpanel_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/itsy.c b/arch/arm/mach-sa1100/itsy.c index 2d23c99c6115..a4af8d58867d 100644 --- a/arch/arm/mach-sa1100/itsy.c +++ b/arch/arm/mach-sa1100/itsy.c @@ -37,4 +37,5 @@ MACHINE_START(ITSY, "Compaq Itsy") BOOT_PARAMS(0xc0000100) MAPIO(itsy_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index c71e512830bd..8943e816a180 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -101,4 +101,5 @@ MACHINE_START(JORNADA720, "HP Jornada 720") BOOT_PARAMS(0xc0000100) MAPIO(jornada720_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 728612961bd5..34ab20118c70 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -43,4 +43,5 @@ MACHINE_START(LART, "LART") BOOT_PARAMS(0xc0000100) MAPIO(lart_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c index 20b6d9a43d1d..84c870c3de49 100644 --- a/arch/arm/mach-sa1100/nanoengine.c +++ b/arch/arm/mach-sa1100/nanoengine.c @@ -49,4 +49,5 @@ MACHINE_START(NANOENGINE, "BSE nanoEngine") FIXUP(fixup_nanoengine) MAPIO(nanoengine_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c index baa3a0313a57..1533fc0ff51c 100644 --- a/arch/arm/mach-sa1100/omnimeter.c +++ b/arch/arm/mach-sa1100/omnimeter.c @@ -59,4 +59,5 @@ MACHINE_START(OMNIMETER, "OmniMeter") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(omnimeter_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c index f7102f4388ed..29922dd70e41 100644 --- a/arch/arm/mach-sa1100/pangolin.c +++ b/arch/arm/mach-sa1100/pangolin.c @@ -40,4 +40,5 @@ MACHINE_START(PANGOLIN, "Dialogue-Pangolin") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(pangolin_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c index 43b89fcc8919..04088629f4c7 100644 --- a/arch/arm/mach-sa1100/pfs168.c +++ b/arch/arm/mach-sa1100/pfs168.c @@ -112,4 +112,5 @@ MACHINE_START(PFS168, "Tulsa") BOOT_PARAMS(0xc0000100) MAPIO(pfs168_map_io) INITIRQ(pfs168_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index b0284ff1c74a..2cdfef622c25 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -31,4 +31,5 @@ MACHINE_START(PLEB, "PLEB") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(pleb_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 0dbe474c7611..8bec82676a3b 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -41,4 +41,5 @@ MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)") BOOT_PARAMS(0xc0000100) MAPIO(shannon_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/sherman.c b/arch/arm/mach-sa1100/sherman.c index c36f46017f53..2e66fbadf16f 100644 --- a/arch/arm/mach-sa1100/sherman.c +++ b/arch/arm/mach-sa1100/sherman.c @@ -27,4 +27,5 @@ MACHINE_START(SHERMAN, "Blazie Engineering Sherman") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(sherman_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 472174365903..b73ec2e18eb0 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -231,4 +231,5 @@ MACHINE_START(SIMPAD, "Simpad") BOOT_PARAMS(0xc0000100) MAPIO(simpad_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c index 5aeb087c45d0..f3b3a6eb8c09 100644 --- a/arch/arm/mach-sa1100/stork.c +++ b/arch/arm/mach-sa1100/stork.c @@ -331,6 +331,7 @@ MACHINE_START(STORK, "Stork Technologies prototype") BOOT_PARAMS(0xc0000100) MAPIO(stork_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c index 09f679e4e67b..76e7d36e71bc 100644 --- a/arch/arm/mach-sa1100/system3.c +++ b/arch/arm/mach-sa1100/system3.c @@ -470,4 +470,5 @@ MACHINE_START(PT_SYSTEM3, "PT System 3") BOOT_PARAMS(0xc0000100) MAPIO(system3_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/include/asm-arm/arch-sa1100/time.h b/arch/arm/mach-sa1100/time.c index d962626154dd..e58463b02e67 100644 --- a/include/asm-arm/arch-sa1100/time.h +++ b/arch/arm/mach-sa1100/time.c @@ -78,19 +78,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) unsigned int next_match; do { - do_leds(); - do_timer(regs); + timer_tick(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ next_match = (OSMR0 += LATCH); - do_set_rtc(); } while ((signed long)(next_match - OSCR) <= 0); - do_profile(regs); - return IRQ_HANDLED; } -void __init time_init(void) +static struct irqaction sa1100_timer_irq = { + .name = "SA11xx Timer Tick", + .flags = SA_INTERRUPT, + .handler = sa1100_timer_interrupt +}; + +void __init sa1100_init_time(void) { struct timespec tv; @@ -101,10 +103,9 @@ void __init time_init(void) tv.tv_sec = sa1100_get_rtc_time(); do_settimeofday(&tv); - timer_irq.handler = sa1100_timer_interrupt; OSMR0 = 0; /* set initial match at 0 */ OSSR = 0xf; /* clear status on all timers */ - setup_irq(IRQ_OST0, &timer_irq); + setup_irq(IRQ_OST0, &sa1100_timer_irq); OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */ OSCR = 0; /* initialize free-running timer, force first match */ } diff --git a/arch/arm/mach-sa1100/trizeps.c b/arch/arm/mach-sa1100/trizeps.c index 199d9cfc5024..f3f1682ecd34 100644 --- a/arch/arm/mach-sa1100/trizeps.c +++ b/arch/arm/mach-sa1100/trizeps.c @@ -228,4 +228,5 @@ MACHINE_START(TRIZEPS, "TRIZEPS") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(trizeps_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c index 501b1bfe8b2b..ab2a523c3b14 100644 --- a/arch/arm/mach-sa1100/xp860.c +++ b/arch/arm/mach-sa1100/xp860.c @@ -89,4 +89,5 @@ MACHINE_START(XP860, "XP860") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(xp860_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c index fd9df1bc9162..46e447fc87d9 100644 --- a/arch/arm/mach-sa1100/yopy.c +++ b/arch/arm/mach-sa1100/yopy.c @@ -91,4 +91,5 @@ MACHINE_START(YOPY, "Yopy") BOOT_PARAMS(0xc0000100) MAPIO(yopy_map_io) INITIRQ(sa1100_init_irq) + INITTIME(sa1100_init_time) MACHINE_END diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index fed8a03ddcf9..e4ae688899c1 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -5,13 +5,18 @@ */ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/sched.h> #include <asm/setup.h> #include <asm/mach-types.h> #include <asm/io.h> +#include <asm/leds.h> +#include <asm/param.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> +#include <asm/mach/time.h> extern void shark_init_irq(void); @@ -24,10 +29,43 @@ static void __init shark_map_io(void) iotable_init(shark_io_desc, ARRAY_SIZE(shark_io_desc)); } +#define IRQ_TIMER 0 +#define HZ_TIME ((1193180 + HZ/2) / HZ) + +static irqreturn_t +shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction shark_timer_irq = { + .name = "Shark Timer Tick", + .flags = SA_INTERRUPT, + .handler = shark_timer_interrupt +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init shark_init_time(void) +{ + unsigned long flags; + + outb(0x34, 0x43); /* binary, mode 0, LSB/MSB, Ch 0 */ + outb(HZ_TIME & 0xff, 0x40); /* LSB of count */ + outb(HZ_TIME >> 8, 0x40); + + setup_irq(IRQ_TIMER, &shark_timer_irq); +} + + MACHINE_START(SHARK, "Shark") MAINTAINER("Alexander Schulz") BOOT_MEM(0x08000000, 0x40000000, 0xe0000000) BOOT_PARAMS(0x08003000) MAPIO(shark_map_io) INITIRQ(shark_init_irq) + INITTIME(shark_init_time) MACHINE_END diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 4c8646c62efa..a2f88df44ab9 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -22,7 +22,9 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/sysdev.h> +#include <linux/interrupt.h> +#include <asm/system.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/irq.h> @@ -33,6 +35,7 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> #include <asm/mach/irq.h> +#include <asm/mach/time.h> #include <asm/mach/map.h> #ifdef CONFIG_MMC #include <asm/mach/mmc.h> @@ -511,11 +514,153 @@ static void __init versatile_init(void) leds_event = versatile_leds_event; } +/* + * Where is the timer (VA)? + */ +#define TIMER0_VA_BASE IO_ADDRESS(VERSATILE_TIMER0_1_BASE) +#define TIMER1_VA_BASE (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20) +#define TIMER2_VA_BASE IO_ADDRESS(VERSATILE_TIMER2_3_BASE) +#define TIMER3_VA_BASE (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20) +#define VA_IC_BASE IO_ADDRESS(VERSATILE_VIC_BASE) + +/* + * How long is the timer interval? + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) +#if TIMER_INTERVAL >= 0x100000 +#define TIMER_RELOAD (TIMER_INTERVAL >> 8) /* Divide by 256 */ +#define TIMER_CTRL 0x88 /* Enable, Clock / 256 */ +#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) +#elif TIMER_INTERVAL >= 0x10000 +#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ +#define TIMER_CTRL 0x84 /* Enable, Clock / 16 */ +#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) +#else +#define TIMER_RELOAD (TIMER_INTERVAL) +#define TIMER_CTRL 0x80 /* Enable */ +#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) +#endif + +#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ + +/* + * What does it look like? + */ +typedef struct TimerStruct { + unsigned long TimerLoad; + unsigned long TimerValue; + unsigned long TimerControl; + unsigned long TimerClear; +} TimerStruct_t; + +extern unsigned long (*gettimeoffset)(void); + +/* + * Returns number of ms since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long versatile_gettimeoffset(void) +{ + volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE; + unsigned long ticks1, ticks2, status; + + /* + * Get the current number of ticks. Note that there is a race + * condition between us reading the timer and checking for + * an interrupt. We get around this by ensuring that the + * counter has not reloaded between our two reads. + */ + ticks2 = timer0->TimerValue & 0xffff; + do { + ticks1 = ticks2; + status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); + ticks2 = timer0->TimerValue & 0xffff; + } while (ticks2 > ticks1); + + /* + * Number of ticks since last interrupt. + */ + ticks1 = TIMER_RELOAD - ticks2; + + /* + * Interrupt pending? If so, we've reloaded once already. + * + * FIXME: Need to check this is effectively timer 0 that expires + */ + if (status & IRQMASK_TIMERINT0_1) + ticks1 += TIMER_RELOAD; + + /* + * Convert the ticks to usecs + */ + return TICKS2USECS(ticks1); +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; + + // ...clear the interrupt + timer0->TimerClear = 1; + + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction versatile_timer_irq = { + .name = "Versatile Timer Tick", + .flags = SA_INTERRUPT, + .handler = versatile_timer_interrupt +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init versatile_init_time(void) +{ + volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; + volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; + volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE; + volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE; + + /* + * set clock frequency: + * VERSATILE_REFCLK is 32KHz + * VERSATILE_TIMCLK is 1MHz + */ + *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= + ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel)); + + /* + * Initialise to a known state (all timers off) + */ + timer0->TimerControl = 0; + timer1->TimerControl = 0; + timer2->TimerControl = 0; + timer3->TimerControl = 0; + + timer0->TimerLoad = TIMER_RELOAD; + timer0->TimerValue = TIMER_RELOAD; + timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE; /* periodic + IE */ + + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); + gettimeoffset = versatile_gettimeoffset; +} + MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") BOOT_MEM(0x00000000, 0x101f1000, 0xf11f1000) BOOT_PARAMS(0x00000100) MAPIO(versatile_map_io) INITIRQ(versatile_init_irq) + INITTIME(versatile_init_time) INIT_MACHINE(versatile_init) MACHINE_END diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ba32817ad59f..545a548b1f69 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -220,7 +220,7 @@ config CPU_SA1100 # XScale config CPU_XSCALE bool - depends on ARCH_IOP3XX || ARCH_ADIFCC || ARCH_PXA || ARCH_IXP4XX + depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX default y select CPU_32v5 select CPU_ABRT_EV5T diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index 5a997a3716fc..32a0984318f6 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -36,12 +36,17 @@ #include <linux/fs.h> #include <linux/smp_lock.h> #include <linux/fs.h> +#include <linux/device.h> +#include <linux/cpu.h> +#include <linux/notifier.h> #include <asm/processor.h> #include <asm/msr.h> #include <asm/uaccess.h> #include <asm/system.h> +static struct class_simple *cpuid_class; + #ifdef CONFIG_SMP struct cpuid_command { @@ -153,20 +158,84 @@ static struct file_operations cpuid_fops = { .open = cpuid_open, }; +static int cpuid_class_simple_device_add(int i) +{ + int err = 0; + struct class_device *class_err; + + class_err = class_simple_device_add(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i); + if (IS_ERR(class_err)) + err = PTR_ERR(class_err); + return err; +} + +static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_ONLINE: + cpuid_class_simple_device_add(cpu); + break; + case CPU_DEAD: + class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu)); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block cpuid_class_cpu_notifier = +{ + .notifier_call = cpuid_class_cpu_callback, +}; + int __init cpuid_init(void) { + int i, err = 0; + i = 0; + if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) { printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n", CPUID_MAJOR); - return -EBUSY; + err = -EBUSY; + goto out; + } + cpuid_class = class_simple_create(THIS_MODULE, "cpuid"); + if (IS_ERR(cpuid_class)) { + err = PTR_ERR(cpuid_class); + goto out_chrdev; } + for_each_online_cpu(i) { + err = cpuid_class_simple_device_add(i); + if (err != 0) + goto out_class; + } + register_cpu_notifier(&cpuid_class_cpu_notifier); - return 0; + err = 0; + goto out; + +out_class: + i = 0; + for_each_online_cpu(i) { + class_simple_device_remove(MKDEV(CPUID_MAJOR, i)); + } + class_simple_destroy(cpuid_class); +out_chrdev: + unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); +out: + return err; } void __exit cpuid_exit(void) { + int cpu = 0; + + for_each_online_cpu(cpu) + class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu)); + class_simple_destroy(cpuid_class); unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); + unregister_cpu_notifier(&cpuid_class_cpu_notifier); } module_init(cpuid_init); diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 0f88098de075..41cb82604f7f 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -1015,15 +1015,23 @@ void __init mp_config_acpi_legacy_irqs (void) for (i = 0; i < 16; i++) { int idx; - for (idx = 0; idx < mp_irq_entries; idx++) - if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS && - (mp_irqs[idx].mpc_dstapic == ioapic) && - (mp_irqs[idx].mpc_srcbusirq == i || - mp_irqs[idx].mpc_dstirq == i)) - break; - - if (idx != mp_irq_entries) - continue; /* IRQ already used */ + for (idx = 0; idx < mp_irq_entries; idx++) { + struct mpc_config_intsrc *irq = mp_irqs + idx; + + /* Do we already have a mapping for this ISA IRQ? */ + if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) + break; + + /* Do we already have a mapping for this IOAPIC pin */ + if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && + (irq->mpc_dstirq == i)) + break; + } + + if (idx != mp_irq_entries) { + printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); + continue; /* IRQ already used */ + } intsrc.mpc_irqtype = mp_INT; intsrc.mpc_srcbusirq = i; /* Identity mapped */ diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index 1a1093e4a4c2..670a71efafb3 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -35,12 +35,17 @@ #include <linux/smp_lock.h> #include <linux/major.h> #include <linux/fs.h> +#include <linux/device.h> +#include <linux/cpu.h> +#include <linux/notifier.h> #include <asm/processor.h> #include <asm/msr.h> #include <asm/uaccess.h> #include <asm/system.h> +static struct class_simple *msr_class; + /* Note: "err" is handled in a funny way below. Otherwise one version of gcc or another breaks. */ @@ -255,20 +260,82 @@ static struct file_operations msr_fops = { .open = msr_open, }; +static int msr_class_simple_device_add(int i) +{ + int err = 0; + struct class_device *class_err; + + class_err = class_simple_device_add(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i); + if (IS_ERR(class_err)) + err = PTR_ERR(class_err); + return err; +} + +static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_ONLINE: + msr_class_simple_device_add(cpu); + break; + case CPU_DEAD: + class_simple_device_remove(MKDEV(MSR_MAJOR, cpu)); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block msr_class_cpu_notifier = +{ + .notifier_call = msr_class_cpu_callback, +}; + int __init msr_init(void) { + int i, err = 0; + i = 0; + if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) { printk(KERN_ERR "msr: unable to get major %d for msr\n", MSR_MAJOR); - return -EBUSY; + err = -EBUSY; + goto out; + } + msr_class = class_simple_create(THIS_MODULE, "msr"); + if (IS_ERR(msr_class)) { + err = PTR_ERR(msr_class); + goto out_chrdev; } + for_each_online_cpu(i) { + err = msr_class_simple_device_add(i); + if (err != 0) + goto out_class; + } + register_cpu_notifier(&msr_class_cpu_notifier); - return 0; + err = 0; + goto out; + +out_class: + i = 0; + for_each_online_cpu(i) + class_simple_device_remove(MKDEV(MSR_MAJOR, i)); + class_simple_destroy(msr_class); +out_chrdev: + unregister_chrdev(MSR_MAJOR, "cpu/msr"); +out: + return err; } void __exit msr_exit(void) { + int cpu = 0; + for_each_online_cpu(cpu) + class_simple_device_remove(MKDEV(MSR_MAJOR, cpu)); + class_simple_destroy(msr_class); unregister_chrdev(MSR_MAJOR, "cpu/msr"); + unregister_cpu_notifier(&msr_class_cpu_notifier); } module_init(msr_init); diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 2b49740fbe10..ac5784c618b2 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1183,6 +1183,7 @@ endmenu source "lib/Kconfig" +source "arch/ppc/oprofile/Kconfig" menu "Kernel hacking" diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index b050a1b03e34..52782b7ae2f1 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -50,6 +50,8 @@ drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/ drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/ drivers-$(CONFIG_8260) += arch/ppc/8260_io/ +drivers-$(CONFIG_OPROFILE) += arch/ppc/oprofile/ + BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm .PHONY: $(BOOT_TARGETS) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 38cd36d6cbe9..873199e435f6 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -253,6 +253,24 @@ _GLOBAL(low_choose_750fx_pll) mtmsr r7 blr +_GLOBAL(low_choose_7447a_dfs) + /* Clear MSR:EE */ + mfmsr r7 + rlwinm r0,r7,0,17,15 + mtmsr r0 + + /* Calc new HID1 value */ + mfspr r4,SPRN_HID1 + insrwi r4,r3,1,9 /* insert parameter into bit 9 */ + sync + mtspr SPRN_HID1,r4 + sync + isync + + /* Return */ + mtmsr r7 + blr + #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ /* void local_save_flags_ptr(unsigned long *flags) */ diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index 96a6138e4109..cfeff0479c2e 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -56,6 +56,7 @@ #include <linux/mc146818rtc.h> #include <linux/time.h> #include <linux/init.h> +#include <linux/profile.h> #include <asm/segment.h> #include <asm/io.h> @@ -107,17 +108,23 @@ static inline int tb_delta(unsigned *jiffy_stamp) { return delta; } -extern unsigned long prof_cpu_mask; -extern unsigned int * prof_buffer; -extern unsigned long prof_len; -extern unsigned long prof_shift; extern char _stext; -static inline void ppc_do_profile (unsigned long nip) +static inline void ppc_do_profile (struct pt_regs *regs) { + unsigned long nip; + extern unsigned long prof_cpu_mask; + + profile_hook(regs); + + if (user_mode(regs)) + return; + if (!prof_buffer) return; + nip = instruction_pointer(regs); + /* * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. * (default is all CPUs.) @@ -156,8 +163,9 @@ void timer_interrupt(struct pt_regs * regs) while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) { jiffy_stamp += tb_ticks_per_jiffy; - if (!user_mode(regs)) - ppc_do_profile(instruction_pointer(regs)); + + ppc_do_profile(regs); + if (smp_processor_id()) continue; diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index ebe93fe949b8..d72c35081da2 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -103,8 +103,7 @@ void die(const char * str, struct pt_regs * fp, long err) do_exit(err); } -void -_exception(int signr, struct pt_regs *regs, int code, unsigned long addr) +void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { siginfo_t info; @@ -200,8 +199,7 @@ static inline int check_io_access(struct pt_regs *regs) #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) #endif -void -MachineCheckException(struct pt_regs *regs) +void MachineCheckException(struct pt_regs *regs) { unsigned long reason = get_mc_reason(regs); @@ -329,8 +327,7 @@ MachineCheckException(struct pt_regs *regs) die("machine check", regs, SIGBUS); } -void -SMIException(struct pt_regs *regs) +void SMIException(struct pt_regs *regs) { debugger(regs); #if !(defined(CONFIG_XMON) || defined(CONFIG_KGDB)) @@ -339,24 +336,21 @@ SMIException(struct pt_regs *regs) #endif } -void -UnknownException(struct pt_regs *regs) +void UnknownException(struct pt_regs *regs) { printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx %s\n", regs->nip, regs->msr, regs->trap, print_tainted()); _exception(SIGTRAP, regs, 0, 0); } -void -InstructionBreakpoint(struct pt_regs *regs) +void InstructionBreakpoint(struct pt_regs *regs) { if (debugger_iabr_match(regs)) return; _exception(SIGTRAP, regs, TRAP_BRKPT, 0); } -void -RunModeException(struct pt_regs *regs) +void RunModeException(struct pt_regs *regs) { _exception(SIGTRAP, regs, 0, 0); } @@ -374,8 +368,7 @@ RunModeException(struct pt_regs *regs) #define INST_MFSPR_PVR 0x7c1f42a6 #define INST_MFSPR_PVR_MASK 0xfc1fffff -static int -emulate_instruction(struct pt_regs *regs) +static int emulate_instruction(struct pt_regs *regs) { u32 instword; u32 rd; @@ -438,8 +431,7 @@ static struct bug_entry *find_bug(unsigned long bugaddr) return module_find_bug(bugaddr); } -int -check_bug_trap(struct pt_regs *regs) +int check_bug_trap(struct pt_regs *regs) { struct bug_entry *bug; unsigned long addr; @@ -476,8 +468,7 @@ check_bug_trap(struct pt_regs *regs) return 0; } -void -ProgramCheckException(struct pt_regs *regs) +void ProgramCheckException(struct pt_regs *regs) { unsigned int reason = get_reason(regs); extern int do_mathemu(struct pt_regs *regs); @@ -550,8 +541,7 @@ ProgramCheckException(struct pt_regs *regs) _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); } -void -SingleStepException(struct pt_regs *regs) +void SingleStepException(struct pt_regs *regs) { regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ if (debugger_sstep(regs)) @@ -559,8 +549,7 @@ SingleStepException(struct pt_regs *regs) _exception(SIGTRAP, regs, TRAP_TRACE, 0); } -void -AlignmentException(struct pt_regs *regs) +void AlignmentException(struct pt_regs *regs) { int fixed; @@ -580,8 +569,7 @@ AlignmentException(struct pt_regs *regs) _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); } -void -StackOverflow(struct pt_regs *regs) +void StackOverflow(struct pt_regs *regs) { printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n", current, regs->gpr[1]); @@ -598,8 +586,7 @@ void nonrecoverable_exception(struct pt_regs *regs) die("nonrecoverable exception", regs, SIGKILL); } -void -trace_syscall(struct pt_regs *regs) +void trace_syscall(struct pt_regs *regs) { printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n", current, current->pid, regs->nip, regs->link, regs->gpr[0], @@ -607,8 +594,7 @@ trace_syscall(struct pt_regs *regs) } #ifdef CONFIG_8xx -void -SoftwareEmulation(struct pt_regs *regs) +void SoftwareEmulation(struct pt_regs *regs) { extern int do_mathemu(struct pt_regs *); extern int Soft_emulate_8xx(struct pt_regs *); @@ -660,8 +646,7 @@ void DebugException(struct pt_regs *regs, unsigned long debug_status) #endif /* CONFIG_4xx || CONFIG_BOOKE */ #if !defined(CONFIG_TAU_INT) -void -TAUException(struct pt_regs *regs) +void TAUException(struct pt_regs *regs) { printk("TAU trap at PC: %lx, MSR: %lx, vector=%lx %s\n", regs->nip, regs->msr, regs->trap, print_tainted()); @@ -683,14 +668,13 @@ void AltivecUnavailException(struct pt_regs *regs) /* The kernel has executed an altivec instruction without first enabling altivec. Whinge but let it do it. */ if (++kernel_altivec_count < 10) - printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%x)\n", + printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n", current, regs->nip); regs->msr |= MSR_VEC; } #ifdef CONFIG_ALTIVEC -void -AltivecAssistException(struct pt_regs *regs) +void AltivecAssistException(struct pt_regs *regs) { int err; @@ -734,8 +718,7 @@ void CacheLockingException(struct pt_regs *regs, unsigned long address, #endif /* CONFIG_FSL_BOOKE */ #ifdef CONFIG_SPE -void -SPEFloatingPointException(struct pt_regs *regs) +void SPEFloatingPointException(struct pt_regs *regs) { unsigned long spefscr; int fpexc_mode; diff --git a/arch/ppc/kernel/vecemu.c b/arch/ppc/kernel/vecemu.c index 1430ef59279c..2411a1cbc638 100644 --- a/arch/ppc/kernel/vecemu.c +++ b/arch/ppc/kernel/vecemu.c @@ -256,8 +256,7 @@ static unsigned int rfin(unsigned int x) return (x + half) & ~(0x7fffff >> exp); } -int -emulate_altivec(struct pt_regs *regs) +int emulate_altivec(struct pt_regs *regs) { unsigned int instr, i; unsigned int va, vb, vc, vd; diff --git a/arch/ppc/oprofile/Kconfig b/arch/ppc/oprofile/Kconfig new file mode 100644 index 000000000000..19d37730b664 --- /dev/null +++ b/arch/ppc/oprofile/Kconfig @@ -0,0 +1,23 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff --git a/arch/ppc/oprofile/Makefile b/arch/ppc/oprofile/Makefile new file mode 100644 index 000000000000..06e7c81ead2e --- /dev/null +++ b/arch/ppc/oprofile/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) init.o diff --git a/arch/ppc/oprofile/init.c b/arch/ppc/oprofile/init.c new file mode 100644 index 000000000000..e4217d66164e --- /dev/null +++ b/arch/ppc/oprofile/init.c @@ -0,0 +1,23 @@ +/** + * @file init.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon <levon@movementarian.org> + */ + +#include <linux/kernel.h> +#include <linux/oprofile.h> +#include <linux/init.h> +#include <linux/errno.h> + +int __init oprofile_arch_init(struct oprofile_operations ** ops) +{ + return -ENODEV; +} + + +void oprofile_arch_exit(void) +{ +} diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index 2c8cec2723ad..b26c7e158792 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -1,7 +1,8 @@ /* * arch/ppc/platforms/pmac_cpufreq.c * - * Copyright (C) 2002 - 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * Copyright (C) 2002 - 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * Copyright (C) 2004 John Steele Scott <toojays@toojays.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -47,6 +48,7 @@ #warning "WARNING, CPUFREQ not recommended on SMP kernels" #endif +extern void low_choose_7447a_dfs(int dfs); extern void low_choose_750fx_pll(int pll); extern void low_sleep_handler(void); extern void openpic_suspend(struct sys_device *sysdev, u32 state); @@ -54,18 +56,27 @@ extern void openpic_resume(struct sys_device *sysdev); extern void enable_kernel_altivec(void); extern void enable_kernel_fp(void); +/* + * Currently, PowerMac cpufreq supports only high & low frequencies + * that are set by the firmware + */ static unsigned int low_freq; static unsigned int hi_freq; static unsigned int cur_freq; -/* Clean that up some day ... use a func ptr or at least an enum... */ -static int cpufreq_uses_pmu; -static int cpufreq_uses_gpios; +/* + * Different models uses different mecanisms to switch the frequency + */ +static int (*set_speed_proc)(int low_speed); +/* + * Some definitions used by the various speedprocs + */ static u32 voltage_gpio; static u32 frequency_gpio; static u32 slew_done_gpio; + #define PMAC_CPU_LOW_SPEED 1 #define PMAC_CPU_HIGH_SPEED 0 @@ -123,9 +134,39 @@ static int __pmac cpu_750fx_cpu_speed(int low_speed) return 0; } +/* Switch CPU speed using DFS */ +static int __pmac dfs_set_cpu_speed(int low_speed) +{ + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/1000); + } else { + /* ramping down, enable aack delay first */ + pmac_call_feature(PMAC_FTR_AACK_DELAY_ENABLE, NULL, 1, 0); + } + + /* set frequency */ + low_choose_7447a_dfs(low_speed); + + if (low_speed == 1) { + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/1000); + } else { + /* ramping up, disable aack delay last */ + pmac_call_feature(PMAC_FTR_AACK_DELAY_ENABLE, NULL, 0, 0); + } + + return 0; +} + + /* Switch CPU speed using slewing GPIOs */ -static int __pmac gpios_set_cpu_speed(unsigned int low_speed) +static int __pmac gpios_set_cpu_speed(int low_speed) { int gpio; @@ -138,7 +179,8 @@ static int __pmac gpios_set_cpu_speed(unsigned int low_speed) } /* Set frequency */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, low_speed ? 0x04 : 0x05); + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, + low_speed ? 0x04 : 0x05); udelay(200); do { set_current_state(TASK_UNINTERRUPTIBLE); @@ -163,7 +205,7 @@ static int __pmac gpios_set_cpu_speed(unsigned int low_speed) /* Switch CPU speed under PMU control */ -static int __pmac pmu_set_cpu_speed(unsigned int low_speed) +static int __pmac pmu_set_cpu_speed(int low_speed) { struct adb_request req; unsigned long save_l2cr; @@ -269,12 +311,7 @@ static int __pmac do_set_cpu_speed(int speed_mode) return 0; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (cpufreq_uses_pmu) - rc = pmu_set_cpu_speed(speed_mode); - else if (cpufreq_uses_gpios) - rc = gpios_set_cpu_speed(speed_mode); - else - rc = cpu_750fx_cpu_speed(speed_mode); + set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; @@ -338,20 +375,137 @@ static struct cpufreq_driver pmac_cpufreq_driver = { }; +static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np = of_find_node_by_name(NULL, + "voltage-gpio"); + struct device_node *freq_gpio_np = of_find_node_by_name(NULL, + "frequency-gpio"); + struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, + "slewing-done"); + u32 *value; + + /* + * Check to see if it's GPIO driven or PMU only + * + * The way we extract the GPIO address is slightly hackish, but it + * works well enough for now. We need to abstract the whole GPIO + * stuff sooner or later anyway + */ + + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (freq_gpio_np) + frequency_gpio = read_gpio(freq_gpio_np); + if (slew_done_gpio_np) + slew_done_gpio = read_gpio(slew_done_gpio_np); + + /* If we use the frequency GPIOs, calculate the min/max speeds based + * on the bus frequencies + */ + if (frequency_gpio && slew_done_gpio) { + int lenp, rc; + u32 *freqs, *ratio; + + freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); + lenp /= sizeof(u32); + if (freqs == NULL || lenp != 2) { + printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); + return 1; + } + ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); + if (ratio == NULL) { + printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); + return 1; + } + + /* Get the min/max bus frequencies */ + low_freq = min(freqs[0], freqs[1]); + hi_freq = max(freqs[0], freqs[1]); + + /* Grrrr.. It _seems_ that the device-tree is lying on the low bus + * frequency, it claims it to be around 84Mhz on some models while + * it appears to be approx. 101Mhz on all. Let's hack around here... + * fortunately, we don't need to be too precise + */ + if (low_freq < 98000000) + low_freq = 101000000; + + /* Convert those to CPU core clocks */ + low_freq = (low_freq * (*ratio)) / 2000; + hi_freq = (hi_freq * (*ratio)) / 2000; + + /* Now we get the frequencies, we read the GPIO to see what is out current + * speed + */ + rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + cur_freq = (rc & 0x01) ? hi_freq : low_freq; + + set_speed_proc = gpios_set_cpu_speed; + return 1; + } + + /* If we use the PMU, look for the min & max frequencies in the + * device-tree + */ + value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree + * here */ + if (low_freq < 100000) + low_freq *= 10; + + value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); + if (!value) + return 1; + hi_freq = (*value) / 1000; + set_speed_proc = pmu_set_cpu_speed; + + return 0; +} + +static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + + /* OF only reports the high frequency */ + hi_freq = cur_freq; + low_freq = cur_freq/2; + if (mfspr(HID1) & HID1_DFS) + cur_freq = low_freq; + else + cur_freq = hi_freq; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (!volt_gpio_np){ + printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); + return 1; + } + + u32 *reg = (u32 *)get_property(volt_gpio_np, "reg", NULL); + voltage_gpio = *reg; + set_speed_proc = dfs_set_cpu_speed; + + return 0; +} + /* Currently, we support the following machines: * * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) + * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) * - iBook2 500 (PMU based, 400Mhz & 500Mhz) * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) - * - Recent MacRISC3 machines + * - Recent MacRISC3 laptops + * - iBook G4s and PowerBook G4s with 7447A CPUs */ static int __init pmac_cpufreq_setup(void) { struct device_node *cpunode; u32 *value; - int has_freq_ctl = 0; if (strstr(cmd_line, "nocpufreq")) return 0; @@ -367,113 +521,36 @@ static int __init pmac_cpufreq_setup(void) goto out; cur_freq = (*value) / 1000; - /* Check for newer machines */ - if (machine_is_compatible("PowerBook3,4") || - machine_is_compatible("PowerBook3,5") || - machine_is_compatible("MacRISC3")) { - struct device_node *volt_gpio_np = of_find_node_by_name(NULL, "voltage-gpio"); - struct device_node *freq_gpio_np = of_find_node_by_name(NULL, "frequency-gpio"); - struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, "slewing-done"); - - /* - * Check to see if it's GPIO driven or PMU only - * - * The way we extract the GPIO address is slightly hackish, but it - * works well enough for now. We need to abstract the whole GPIO - * stuff sooner or later anyway - */ - - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (freq_gpio_np) - frequency_gpio = read_gpio(freq_gpio_np); - if (slew_done_gpio_np) - slew_done_gpio = read_gpio(slew_done_gpio_np); - - /* If we use the frequency GPIOs, calculate the min/max speeds based - * on the bus frequencies - */ - if (frequency_gpio && slew_done_gpio) { - int lenp, rc; - u32 *freqs, *ratio; - - freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); - lenp /= sizeof(u32); - if (freqs == NULL || lenp != 2) { - printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); - goto out; - } - ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); - if (ratio == NULL) { - printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); - goto out; - } - - /* Get the min/max bus frequencies */ - low_freq = min(freqs[0], freqs[1]); - hi_freq = max(freqs[0], freqs[1]); - - /* Grrrr.. It _seems_ that the device-tree is lying on the low bus - * frequency, it claims it to be around 84Mhz on some models while - * it appears to be approx. 101Mhz on all. Let's hack around here... - * fortunately, we don't need to be too precise - */ - if (low_freq < 98000000) - low_freq = 101000000; - - /* Convert those to CPU core clocks */ - low_freq = (low_freq * (*ratio)) / 2000; - hi_freq = (hi_freq * (*ratio)) / 2000; - - /* Now we get the frequencies, we read the GPIO to see what is out current - * speed - */ - rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - cur_freq = (rc & 0x01) ? hi_freq : low_freq; - - has_freq_ctl = 1; - cpufreq_uses_gpios = 1; - goto out; - } - - /* If we use the PMU, look for the min & max frequencies in the - * device-tree - */ - value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); - if (!value) - goto out; - low_freq = (*value) / 1000; - /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree - * here */ - if (low_freq < 100000) - low_freq *= 10; - - value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); - if (!value) - goto out; - hi_freq = (*value) / 1000; - has_freq_ctl = 1; - cpufreq_uses_pmu = 1; - } + /* Check for 7447A based iBook G4 or PowerBook */ + if (machine_is_compatible("PowerBook6,5") || + machine_is_compatible("PowerBook6,4") || + machine_is_compatible("PowerBook5,5") || + machine_is_compatible("PowerBook5,4")) { + pmac_cpufreq_init_7447A(cpunode); + /* Check for other MacRISC3 machines */ + } else if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5") || + machine_is_compatible("MacRISC3")) { + pmac_cpufreq_init_MacRISC3(cpunode); /* Else check for iBook2 500 */ - else if (machine_is_compatible("PowerBook4,1")) { + } else if (machine_is_compatible("PowerBook4,1")) { /* We only know about 500Mhz model */ if (cur_freq < 450000 || cur_freq > 550000) goto out; hi_freq = cur_freq; low_freq = 400000; - has_freq_ctl = 1; - cpufreq_uses_pmu = 1; + set_speed_proc = pmu_set_cpu_speed; } - /* Else check for TiPb 500 */ + /* Else check for TiPb 400 & 500 */ else if (machine_is_compatible("PowerBook3,2")) { - /* We only know about 500Mhz model */ - if (cur_freq < 450000 || cur_freq > 550000) + /* We only know about the 400 MHz and the 500Mhz model + * they both have 300 MHz as low frequency + */ + if (cur_freq < 350000 || cur_freq > 550000) goto out; hi_freq = cur_freq; low_freq = 300000; - has_freq_ctl = 1; - cpufreq_uses_pmu = 1; + set_speed_proc = pmu_set_cpu_speed; } /* Else check for 750FX */ else if (PVR_VER(mfspr(PVR)) == 0x7000) { @@ -483,21 +560,19 @@ static int __init pmac_cpufreq_setup(void) value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); if (!value) goto out; - low_freq = (*value) / 1000; - cpufreq_uses_pmu = 0; - has_freq_ctl = 1; + low_freq = (*value) / 1000; + set_speed_proc = cpu_750fx_cpu_speed; } out: - if (!has_freq_ctl) + if (set_speed_proc == NULL) return -ENODEV; pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz, switch method: %s\n", - low_freq/1000, hi_freq/1000, cur_freq/1000, - cpufreq_uses_pmu ? "PMU" : (cpufreq_uses_gpios ? "GPIOs" : "CPU")); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", + low_freq/1000, hi_freq/1000, cur_freq/1000); return cpufreq_register_driver(&pmac_cpufreq_driver); } diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index abd06fc82a34..35714de243b8 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c @@ -1282,6 +1282,25 @@ core99_firewire_cable_power(struct device_node* node, long param, long value) return 0; } +static long __pmac +intrepid_aack_delay_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + + if (uninorth_rev < 0xd2) + return -ENODEV; + + LOCK(flags); + if (param) + UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); + else + UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); + UNLOCK(flags); + + return 0; +} + + #endif /* CONFIG_POWER4 */ static long __pmac @@ -1914,6 +1933,7 @@ static struct feature_table_entry intrepid_features[] __pmacdata = { { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, { PMAC_FTR_READ_GPIO, core99_read_gpio }, { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, + { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable }, { 0, NULL } }; @@ -2116,6 +2136,14 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, }, + { "PowerBook5,4", "PowerBook G4 15\"", + PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, + PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, + }, + { "PowerBook5,5", "PowerBook G4 17\"", + PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, + PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, + }, { "PowerBook6,1", "PowerBook G4 12\"", PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, @@ -2128,6 +2156,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, }, + { "PowerBook6,4", "PowerBook G4 12\"", + PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, + PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, + }, { "PowerBook6,5", "iBook G4", PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index c36dd89a4e3b..fda27888edd3 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -56,4 +56,6 @@ ifdef CONFIG_SMP obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o endif +obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o + CFLAGS_ioctl32.o += -Ifs/ diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index 593319735e5e..4de4982f58f3 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -544,9 +544,39 @@ AlignmentException(struct pt_regs *regs) void AltivecAssistException(struct pt_regs *regs) { + int err; + siginfo_t info; + + if (!user_mode(regs)) { + printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode" + " at %lx\n", regs->nip); + die("Kernel VMX/Altivec assist exception", regs, SIGILL); + } + flush_altivec_to_thread(current); - /* XXX quick hack for now: set the non-Java bit in the VSCR */ - current->thread.vscr.u[3] |= 0x10000; + + err = emulate_altivec(regs); + if (err == 0) { + regs->nip += 4; /* skip emulated instruction */ + emulate_single_step(regs); + return; + } + + if (err == -EFAULT) { + /* got an error reading the instruction */ + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = SEGV_MAPERR; + info.si_addr = (void *) regs->nip; + force_sig_info(SIGSEGV, &info, current); + } else { + /* didn't recognize the instruction */ + /* XXX quick hack for now: set the non-Java bit in the VSCR */ + if (printk_ratelimit()) + printk(KERN_ERR "Unrecognized altivec instruction " + "in %s at %lx\n", current->comm, regs->nip); + current->thread.vscr.u[3] |= 0x10000; + } } #endif /* CONFIG_ALTIVEC */ diff --git a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c new file mode 100644 index 000000000000..1430ef59279c --- /dev/null +++ b/arch/ppc64/kernel/vecemu.c @@ -0,0 +1,346 @@ +/* + * Routines to emulate some Altivec/VMX instructions, specifically + * those that can trap when given denormalized operands in Java mode. + */ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <asm/ptrace.h> +#include <asm/processor.h> +#include <asm/uaccess.h> + +/* Functions in vector.S */ +extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); +extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); +extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); +extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); +extern void vrefp(vector128 *dst, vector128 *src); +extern void vrsqrtefp(vector128 *dst, vector128 *src); +extern void vexptep(vector128 *dst, vector128 *src); + +static unsigned int exp2s[8] = { + 0x800000, + 0x8b95c2, + 0x9837f0, + 0xa5fed7, + 0xb504f3, + 0xc5672a, + 0xd744fd, + 0xeac0c7 +}; + +/* + * Computes an estimate of 2^x. The `s' argument is the 32-bit + * single-precision floating-point representation of x. + */ +static unsigned int eexp2(unsigned int s) +{ + int exp, pwr; + unsigned int mant, frac; + + /* extract exponent field from input */ + exp = ((s >> 23) & 0xff) - 127; + if (exp > 7) { + /* check for NaN input */ + if (exp == 128 && (s & 0x7fffff) != 0) + return s | 0x400000; /* return QNaN */ + /* 2^-big = 0, 2^+big = +Inf */ + return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ + } + if (exp < -23) + return 0x3f800000; /* 1.0 */ + + /* convert to fixed point integer in 9.23 representation */ + pwr = (s & 0x7fffff) | 0x800000; + if (exp > 0) + pwr <<= exp; + else + pwr >>= -exp; + if (s & 0x80000000) + pwr = -pwr; + + /* extract integer part, which becomes exponent part of result */ + exp = (pwr >> 23) + 126; + if (exp >= 254) + return 0x7f800000; + if (exp < -23) + return 0; + + /* table lookup on top 3 bits of fraction to get mantissa */ + mant = exp2s[(pwr >> 20) & 7]; + + /* linear interpolation using remaining 20 bits of fraction */ + asm("mulhwu %0,%1,%2" : "=r" (frac) + : "r" (pwr << 12), "r" (0x172b83ff)); + asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); + mant += frac; + + if (exp >= 0) + return mant + (exp << 23); + + /* denormalized result */ + exp = -exp; + mant += 1 << (exp - 1); + return mant >> exp; +} + +/* + * Computes an estimate of log_2(x). The `s' argument is the 32-bit + * single-precision floating-point representation of x. + */ +static unsigned int elog2(unsigned int s) +{ + int exp, mant, lz, frac; + + exp = s & 0x7f800000; + mant = s & 0x7fffff; + if (exp == 0x7f800000) { /* Inf or NaN */ + if (mant != 0) + s |= 0x400000; /* turn NaN into QNaN */ + return s; + } + if ((exp | mant) == 0) /* +0 or -0 */ + return 0xff800000; /* return -Inf */ + + if (exp == 0) { + /* denormalized */ + asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); + mant <<= lz - 8; + exp = (-118 - lz) << 23; + } else { + mant |= 0x800000; + exp -= 127 << 23; + } + + if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ + exp |= 0x400000; /* 0.5 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ + } + if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ + exp |= 0x200000; /* 0.25 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ + } + if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ + exp |= 0x100000; /* 0.125 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ + } + if (mant > 0x800000) { /* 1.0 * 2^23 */ + /* calculate (mant - 1) * 1.381097463 */ + /* 1.381097463 == 0.125 / (2^0.125 - 1) */ + asm("mulhwu %0,%1,%2" : "=r" (frac) + : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); + exp += frac; + } + s = exp & 0x80000000; + if (exp != 0) { + if (s) + exp = -exp; + asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); + lz = 8 - lz; + if (lz > 0) + exp >>= lz; + else if (lz < 0) + exp <<= -lz; + s += ((lz + 126) << 23) + exp; + } + return s; +} + +#define VSCR_SAT 1 + +static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) +{ + int exp, mant; + + exp = (x >> 23) & 0xff; + mant = x & 0x7fffff; + if (exp == 255 && mant != 0) + return 0; /* NaN -> 0 */ + exp = exp - 127 + scale; + if (exp < 0) + return 0; /* round towards zero */ + if (exp >= 31) { + /* saturate, unless the result would be -2^31 */ + if (x + (scale << 23) != 0xcf000000) + *vscrp |= VSCR_SAT; + return (x & 0x80000000)? 0x80000000: 0x7fffffff; + } + mant |= 0x800000; + mant = (mant << 7) >> (30 - exp); + return (x & 0x80000000)? -mant: mant; +} + +static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) +{ + int exp; + unsigned int mant; + + exp = (x >> 23) & 0xff; + mant = x & 0x7fffff; + if (exp == 255 && mant != 0) + return 0; /* NaN -> 0 */ + exp = exp - 127 + scale; + if (exp < 0) + return 0; /* round towards zero */ + if (x & 0x80000000) { + /* negative => saturate to 0 */ + *vscrp |= VSCR_SAT; + return 0; + } + if (exp >= 32) { + /* saturate */ + *vscrp |= VSCR_SAT; + return 0xffffffff; + } + mant |= 0x800000; + mant = (mant << 8) >> (31 - exp); + return mant; +} + +/* Round to floating integer, towards 0 */ +static unsigned int rfiz(unsigned int x) +{ + int exp; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if (exp < 0) + return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ + return x & ~(0x7fffff >> exp); +} + +/* Round to floating integer, towards +/- Inf */ +static unsigned int rfii(unsigned int x) +{ + int exp, mask; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if ((x & 0x7fffffff) == 0) + return x; /* +/-0 -> +/-0 */ + if (exp < 0) + /* 0 < |x| < 1.0 rounds to +/- 1.0 */ + return (x & 0x80000000) | 0x3f800000; + mask = 0x7fffff >> exp; + /* mantissa overflows into exponent - that's OK, + it can't overflow into the sign bit */ + return (x + mask) & ~mask; +} + +/* Round to floating integer, to nearest */ +static unsigned int rfin(unsigned int x) +{ + int exp, half; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if (exp < -1) + return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ + if (exp == -1) + /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ + return (x & 0x80000000) | 0x3f800000; + half = 0x400000 >> exp; + /* add 0.5 to the magnitude and chop off the fraction bits */ + return (x + half) & ~(0x7fffff >> exp); +} + +int +emulate_altivec(struct pt_regs *regs) +{ + unsigned int instr, i; + unsigned int va, vb, vc, vd; + vector128 *vrs; + + if (get_user(instr, (unsigned int *) regs->nip)) + return -EFAULT; + if ((instr >> 26) != 4) + return -EINVAL; /* not an altivec instruction */ + vd = (instr >> 21) & 0x1f; + va = (instr >> 16) & 0x1f; + vb = (instr >> 11) & 0x1f; + vc = (instr >> 6) & 0x1f; + + vrs = current->thread.vr; + switch (instr & 0x3f) { + case 10: + switch (vc) { + case 0: /* vaddfp */ + vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); + break; + case 1: /* vsubfp */ + vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); + break; + case 4: /* vrefp */ + vrefp(&vrs[vd], &vrs[vb]); + break; + case 5: /* vrsqrtefp */ + vrsqrtefp(&vrs[vd], &vrs[vb]); + break; + case 6: /* vexptefp */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = eexp2(vrs[vb].u[i]); + break; + case 7: /* vlogefp */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = elog2(vrs[vb].u[i]); + break; + case 8: /* vrfin */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = rfin(vrs[vb].u[i]); + break; + case 9: /* vrfiz */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = rfiz(vrs[vb].u[i]); + break; + case 10: /* vrfip */ + for (i = 0; i < 4; ++i) { + u32 x = vrs[vb].u[i]; + x = (x & 0x80000000)? rfiz(x): rfii(x); + vrs[vd].u[i] = x; + } + break; + case 11: /* vrfim */ + for (i = 0; i < 4; ++i) { + u32 x = vrs[vb].u[i]; + x = (x & 0x80000000)? rfii(x): rfiz(x); + vrs[vd].u[i] = x; + } + break; + case 14: /* vctuxs */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, + ¤t->thread.vscr.u[3]); + break; + case 15: /* vctsxs */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, + ¤t->thread.vscr.u[3]); + break; + default: + return -EINVAL; + } + break; + case 46: /* vmaddfp */ + vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); + break; + case 47: /* vnmsubfp */ + vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S new file mode 100644 index 000000000000..940cd7287346 --- /dev/null +++ b/arch/ppc64/kernel/vector.S @@ -0,0 +1,172 @@ +#include <asm/ppc_asm.h> +#include <asm/processor.h> + +/* + * The routines below are in assembler so we can closely control the + * usage of floating-point registers. These routines must be called + * with preempt disabled. + */ + .section ".toc","aw" +fpzero: + .tc FD_0_0[TC],0 +fpone: + .tc FD_3ff00000_0[TC],0x3ff0000000000000 /* 1.0 */ +fphalf: + .tc FD_3fe00000_0[TC],0x3fe0000000000000 /* 0.5 */ + + .text +/* + * Internal routine to enable floating point and set FPSCR to 0. + * Don't call it from C; it doesn't use the normal calling convention. + */ +fpenable: + mfmsr r10 + ori r11,r10,MSR_FP + mtmsr r11 + isync + stfd fr31,-8(r1) + stfd fr0,-16(r1) + stfd fr1,-24(r1) + mffs fr31 + lfd fr1,fpzero@toc(r2) + mtfsf 0xff,fr1 + blr + +fpdisable: + mtlr r12 + mtfsf 0xff,fr31 + lfd fr1,-24(r1) + lfd fr0,-16(r1) + lfd fr31,-8(r1) + mtmsr r10 + isync + blr + +/* + * Vector add, floating point. + */ +_GLOBAL(vaddfp) + mflr r12 + bl fpenable + li r0,4 + mtctr r0 + li r6,0 +1: lfsx fr0,r4,r6 + lfsx fr1,r5,r6 + fadds fr0,fr0,fr1 + stfsx fr0,r3,r6 + addi r6,r6,4 + bdnz 1b + b fpdisable + +/* + * Vector subtract, floating point. + */ +_GLOBAL(vsubfp) + mflr r12 + bl fpenable + li r0,4 + mtctr r0 + li r6,0 +1: lfsx fr0,r4,r6 + lfsx fr1,r5,r6 + fsubs fr0,fr0,fr1 + stfsx fr0,r3,r6 + addi r6,r6,4 + bdnz 1b + b fpdisable + +/* + * Vector multiply and add, floating point. + */ +_GLOBAL(vmaddfp) + mflr r12 + bl fpenable + stfd fr2,-32(r1) + li r0,4 + mtctr r0 + li r7,0 +1: lfsx fr0,r4,r7 + lfsx fr1,r5,r7 + lfsx fr2,r6,r7 + fmadds fr0,fr0,fr1,fr2 + stfsx fr0,r3,r7 + addi r7,r7,4 + bdnz 1b + lfd fr2,-32(r1) + b fpdisable + +/* + * Vector negative multiply and subtract, floating point. + */ +_GLOBAL(vnmsubfp) + mflr r12 + bl fpenable + stfd fr2,-32(r1) + li r0,4 + mtctr r0 + li r7,0 +1: lfsx fr0,r4,r7 + lfsx fr1,r5,r7 + lfsx fr2,r6,r7 + fnmsubs fr0,fr0,fr1,fr2 + stfsx fr0,r3,r7 + addi r7,r7,4 + bdnz 1b + lfd fr2,-32(r1) + b fpdisable + +/* + * Vector reciprocal estimate. We just compute 1.0/x. + * r3 -> destination, r4 -> source. + */ +_GLOBAL(vrefp) + mflr r12 + bl fpenable + li r0,4 + lfd fr1,fpone@toc(r2) + mtctr r0 + li r6,0 +1: lfsx fr0,r4,r6 + fdivs fr0,fr1,fr0 + stfsx fr0,r3,r6 + addi r6,r6,4 + bdnz 1b + b fpdisable + +/* + * Vector reciprocal square-root estimate, floating point. + * We use the frsqrte instruction for the initial estimate followed + * by 2 iterations of Newton-Raphson to get sufficient accuracy. + * r3 -> destination, r4 -> source. + */ +_GLOBAL(vrsqrtefp) + mflr r12 + bl fpenable + stfd fr2,-32(r1) + stfd fr3,-40(r1) + stfd fr4,-48(r1) + stfd fr5,-56(r1) + li r0,4 + lfd fr4,fpone@toc(r2) + lfd fr5,fphalf@toc(r2) + mtctr r0 + li r6,0 +1: lfsx fr0,r4,r6 + frsqrte fr1,fr0 /* r = frsqrte(s) */ + fmuls fr3,fr1,fr0 /* r * s */ + fmuls fr2,fr1,fr5 /* r * 0.5 */ + fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */ + fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */ + fmuls fr3,fr1,fr0 /* r * s */ + fmuls fr2,fr1,fr5 /* r * 0.5 */ + fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */ + fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */ + stfsx fr1,r3,r6 + addi r6,r6,4 + bdnz 1b + lfd fr5,-56(r1) + lfd fr4,-48(r1) + lfd fr3,-40(r1) + lfd fr2,-32(r1) + b fpdisable diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index c43bb7bb23a3..c5b647febac4 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -859,16 +859,22 @@ void __init mp_config_acpi_legacy_irqs (void) for (i = 0; i < 16; i++) { int idx; - for (idx = 0; idx < mp_irq_entries; idx++) - if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS && - (mp_irqs[idx].mpc_dstapic == ioapic) && - (mp_irqs[idx].mpc_srcbusirq == i || - mp_irqs[idx].mpc_dstirq == i)) - break; + for (idx = 0; idx < mp_irq_entries; idx++) { + struct mpc_config_intsrc *irq = mp_irqs + idx; + + /* Do we already have a mapping for this ISA IRQ? */ + if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) + break; + + /* Do we already have a mapping for this IOAPIC pin */ + if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && + (irq->mpc_dstirq == i)) + break; + } if (idx != mp_irq_entries) { printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); - continue; /* IRQ already used */ + continue; /* IRQ already used */ } intsrc.mpc_irqtype = mp_INT; diff --git a/drivers/base/base.h b/drivers/base/base.h index da16cc5c9e30..8d1e8bd48632 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -6,12 +6,13 @@ extern void bus_remove_driver(struct device_driver *); static inline struct class_device *to_class_dev(struct kobject *obj) { - return container_of(obj,struct class_device,kobj); + return container_of(obj, struct class_device, kobj); } + static inline struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) { - return container_of(_attr,struct class_device_attribute,attr); + return container_of(_attr, struct class_device_attribute, attr); } diff --git a/drivers/base/bus.c b/drivers/base/bus.c index b40af6a72afe..02ff97df6dee 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -3,7 +3,7 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * */ @@ -17,17 +17,17 @@ #include "base.h" #include "power/power.h" -#define to_dev(node) container_of(node,struct device,bus_list) -#define to_drv(node) container_of(node,struct device_driver,kobj.entry) +#define to_dev(node) container_of(node, struct device, bus_list) +#define to_drv(node) container_of(node, struct device_driver, kobj.entry) -#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr) -#define to_bus(obj) container_of(obj,struct bus_type,subsys.kset.kobj) +#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) +#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj) /* * sysfs bindings for drivers */ -#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr) +#define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) #define to_driver(obj) container_of(obj, struct device_driver, kobj) @@ -39,12 +39,12 @@ drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) ssize_t ret = 0; if (drv_attr->show) - ret = drv_attr->show(drv,buf); + ret = drv_attr->show(drv, buf); return ret; } static ssize_t -drv_attr_store(struct kobject * kobj, struct attribute * attr, +drv_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct driver_attribute * drv_attr = to_drv_attr(attr); @@ -52,7 +52,7 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (drv_attr->store) - ret = drv_attr->store(drv,buf,count); + ret = drv_attr->store(drv, buf, count); return ret; } @@ -87,12 +87,12 @@ bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) ssize_t ret = 0; if (bus_attr->show) - ret = bus_attr->show(bus,buf); + ret = bus_attr->show(bus, buf); return ret; } static ssize_t -bus_attr_store(struct kobject * kobj, struct attribute * attr, +bus_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct bus_attribute * bus_attr = to_bus_attr(attr); @@ -100,7 +100,7 @@ bus_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (bus_attr->store) - ret = bus_attr->store(bus,buf,count); + ret = bus_attr->store(bus, buf, count); return ret; } @@ -113,7 +113,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) { int error; if (get_bus(bus)) { - error = sysfs_create_file(&bus->subsys.kset.kobj,&attr->attr); + error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr); put_bus(bus); } else error = -EINVAL; @@ -123,7 +123,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) { if (get_bus(bus)) { - sysfs_remove_file(&bus->subsys.kset.kobj,&attr->attr); + sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr); put_bus(bus); } } @@ -133,7 +133,7 @@ static struct kobj_type ktype_bus = { }; -decl_subsys(bus,&ktype_bus,NULL); +decl_subsys(bus, &ktype_bus, NULL); /** * bus_for_each_dev - device iterator. @@ -151,10 +151,10 @@ decl_subsys(bus,&ktype_bus,NULL); * * NOTE: The device that returns a non-zero value is not retained * in any way, nor is its refcount incremented. If the caller needs - * to retain this data, it should do, and increment the reference + * to retain this data, it should do, and increment the reference * count in the supplied callback. */ -int bus_for_each_dev(struct bus_type * bus, struct device * start, +int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *)) { struct device *dev; @@ -170,7 +170,7 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, down_read(&bus->subsys.rwsem); list_for_each_entry_continue(dev, head, bus_list) { get_device(dev); - error = fn(dev,data); + error = fn(dev, data); put_device(dev); if (error) break; @@ -193,7 +193,7 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, * and return it. If @start is not NULL, we use it as the head * of the list. * - * NOTE: we don't return the driver that returns a non-zero + * NOTE: we don't return the driver that returns a non-zero * value, nor do we leave the reference count incremented for that * driver. If the caller needs to know that info, it must set it * in the callback. It must also be sure to increment the refcount @@ -216,7 +216,7 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, down_read(&bus->subsys.rwsem); list_for_each_entry_continue(drv, head, kobj.entry) { get_driver(drv); - error = fn(drv,data); + error = fn(drv, data); put_driver(drv); if(error) break; @@ -233,8 +233,8 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, * Allow manual attachment of a driver to a deivce. * Caller must have already set @dev->driver. * - * Note that this does not modify the bus reference count - * nor take the bus's rwsem. Please verify those are accounted + * Note that this does not modify the bus reference count + * nor take the bus's rwsem. Please verify those are accounted * for before calling this. (It is ok to call with no other effort * from a driver's probe() method.) */ @@ -242,9 +242,9 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void device_bind_driver(struct device * dev) { pr_debug("bound device '%s' to driver '%s'\n", - dev->bus_id,dev->driver->name); - list_add_tail(&dev->driver_list,&dev->driver->devices); - sysfs_create_link(&dev->driver->kobj,&dev->kobj, + dev->bus_id, dev->driver->name); + list_add_tail(&dev->driver_list, &dev->driver->devices); + sysfs_create_link(&dev->driver->kobj, &dev->kobj, kobject_name(&dev->kobj)); } @@ -255,18 +255,18 @@ void device_bind_driver(struct device * dev) * @drv: driver. * * First, we call the bus's match function, which should compare - * the device IDs the driver supports with the device IDs of the - * device. Note we don't do this ourselves because we don't know + * the device IDs the driver supports with the device IDs of the + * device. Note we don't do this ourselves because we don't know * the format of the ID structures, nor what is to be considered * a match and what is not. - * - * If we find a match, we call @drv->probe(@dev) if it exists, and + * + * If we find a match, we call @drv->probe(@dev) if it exists, and * call attach() above. */ static int bus_match(struct device * dev, struct device_driver * drv) { int error = -ENODEV; - if (dev->bus->match(dev,drv)) { + if (dev->bus->match(dev, drv)) { dev->driver = drv; if (drv->probe) { if ((error = drv->probe(dev))) { @@ -285,7 +285,7 @@ static int bus_match(struct device * dev, struct device_driver * drv) * device_attach - try to attach device to a driver. * @dev: device. * - * Walk the list of drivers that the bus has and call bus_match() + * Walk the list of drivers that the bus has and call bus_match() * for each pair. If a compatible pair is found, break out and return. */ static int device_attach(struct device * dev) @@ -300,15 +300,15 @@ static int device_attach(struct device * dev) } if (bus->match) { - list_for_each(entry,&bus->drivers.list) { + list_for_each(entry, &bus->drivers.list) { struct device_driver * drv = to_drv(entry); - error = bus_match(dev,drv); - if (!error ) + error = bus_match(dev, drv); + if (!error) /* success, driver matched */ - return 1; - if (error != -ENODEV) + return 1; + if (error != -ENODEV) /* driver matched but the probe failed */ - printk(KERN_WARNING + printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev->bus_id, error); } @@ -327,7 +327,7 @@ static int device_attach(struct device * dev) * If bus_match() returns 0 and the @dev->driver is set, we've found * a compatible pair. * - * Note that we ignore the -ENODEV error from bus_match(), since it's + * Note that we ignore the -ENODEV error from bus_match(), since it's * perfectly valid for a driver not to bind to any devices. */ void driver_attach(struct device_driver * drv) @@ -339,13 +339,13 @@ void driver_attach(struct device_driver * drv) if (!bus->match) return; - list_for_each(entry,&bus->devices.list) { - struct device * dev = container_of(entry,struct device,bus_list); + list_for_each(entry, &bus->devices.list) { + struct device * dev = container_of(entry, struct device, bus_list); if (!dev->driver) { - error = bus_match(dev,drv); + error = bus_match(dev, drv); if (error && (error != -ENODEV)) /* driver matched but the probe failed */ - printk(KERN_WARNING + printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev->bus_id, error); } @@ -367,7 +367,7 @@ void device_release_driver(struct device * dev) { struct device_driver * drv = dev->driver; if (drv) { - sysfs_remove_link(&drv->kobj,kobject_name(&dev->kobj)); + sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); list_del_init(&dev->driver_list); device_detach_shutdown(dev); if (drv->remove) @@ -385,13 +385,44 @@ void device_release_driver(struct device * dev) static void driver_detach(struct device_driver * drv) { struct list_head * entry, * next; - list_for_each_safe(entry,next,&drv->devices) { - struct device * dev = container_of(entry,struct device,driver_list); + list_for_each_safe(entry, next, &drv->devices) { + struct device * dev = container_of(entry, struct device, driver_list); device_release_driver(dev); } +} + +static int device_add_attrs(struct bus_type * bus, struct device * dev) +{ + int error = 0; + int i; + + if (bus->dev_attrs) { + for (i = 0; attr_name(bus->dev_attrs[i]); i++) { + error = device_create_file(dev,&bus->dev_attrs[i]); + if (error) + goto Err; + } + } + Done: + return error; + Err: + while (--i >= 0) + device_remove_file(dev,&bus->dev_attrs[i]); + goto Done; +} + + +static void device_remove_attrs(struct bus_type * bus, struct device * dev) +{ + int i; + if (bus->dev_attrs) { + for (i = 0; attr_name(bus->dev_attrs[i]); i++) + device_remove_file(dev,&bus->dev_attrs[i]); + } } + /** * bus_add_device - add device to bus * @dev: device being added @@ -407,11 +438,12 @@ int bus_add_device(struct device * dev) if (bus) { down_write(&dev->bus->subsys.rwsem); - pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id); - list_add_tail(&dev->bus_list,&dev->bus->devices.list); + pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); + list_add_tail(&dev->bus_list, &dev->bus->devices.list); device_attach(dev); up_write(&dev->bus->subsys.rwsem); - sysfs_create_link(&bus->devices.kobj,&dev->kobj,dev->bus_id); + device_add_attrs(bus, dev); + sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); } return error; } @@ -428,9 +460,10 @@ int bus_add_device(struct device * dev) void bus_remove_device(struct device * dev) { if (dev->bus) { - sysfs_remove_link(&dev->bus->devices.kobj,dev->bus_id); + sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); + device_remove_attrs(dev->bus, dev); down_write(&dev->bus->subsys.rwsem); - pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id); + pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); device_release_driver(dev); list_del_init(&dev->bus_list); up_write(&dev->bus->subsys.rwsem); @@ -450,8 +483,8 @@ int bus_add_driver(struct device_driver * drv) int error = 0; if (bus) { - pr_debug("bus %s: add driver %s\n",bus->name,drv->name); - error = kobject_set_name(&drv->kobj,drv->name); + pr_debug("bus %s: add driver %s\n", bus->name, drv->name); + error = kobject_set_name(&drv->kobj, drv->name); if (error) { put_bus(bus); return error; @@ -484,7 +517,7 @@ void bus_remove_driver(struct device_driver * drv) { if (drv->bus) { down_write(&drv->bus->subsys.rwsem); - pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name); + pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); driver_detach(drv); up_write(&drv->bus->subsys.rwsem); kobject_unregister(&drv->kobj); @@ -526,7 +559,7 @@ int bus_rescan_devices(struct bus_type * bus) struct bus_type * get_bus(struct bus_type * bus) { - return bus ? container_of(subsys_get(&bus->subsys),struct bus_type,subsys) : NULL; + return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL; } void put_bus(struct bus_type * bus) @@ -545,29 +578,64 @@ void put_bus(struct bus_type * bus) struct bus_type * find_bus(char * name) { - struct kobject * k = kset_find_obj(&bus_subsys.kset,name); + struct kobject * k = kset_find_obj(&bus_subsys.kset, name); return k ? to_bus(k) : NULL; } + +/** + * bus_add_attrs - Add default attributes for this bus. + * @bus: Bus that has just been registered. + */ + +static int bus_add_attrs(struct bus_type * bus) +{ + int error = 0; + int i; + + if (bus->bus_attrs) { + for (i = 0; attr_name(bus->bus_attrs[i]); i++) { + if ((error = bus_create_file(bus,&bus->bus_attrs[i]))) + goto Err; + } + } + Done: + return error; + Err: + while (--i >= 0) + bus_remove_file(bus,&bus->bus_attrs[i]); + goto Done; +} + +static void bus_remove_attrs(struct bus_type * bus) +{ + int i; + + if (bus->bus_attrs) { + for (i = 0; attr_name(bus->bus_attrs[i]); i++) + bus_remove_file(bus,&bus->bus_attrs[i]); + } +} + /** * bus_register - register a bus with the system. * @bus: bus. * * Once we have that, we registered the bus with the kobject * infrastructure, then register the children subsystems it has: - * the devices and drivers that belong to the bus. + * the devices and drivers that belong to the bus. */ int bus_register(struct bus_type * bus) { int retval; - retval = kobject_set_name(&bus->subsys.kset.kobj,bus->name); + retval = kobject_set_name(&bus->subsys.kset.kobj, bus->name); if (retval) goto out; - subsys_set_kset(bus,bus_subsys); + subsys_set_kset(bus, bus_subsys); retval = subsystem_register(&bus->subsys); - if (retval) + if (retval) goto out; kobject_set_name(&bus->devices.kobj, "devices"); @@ -582,8 +650,9 @@ int bus_register(struct bus_type * bus) retval = kset_register(&bus->drivers); if (retval) goto bus_drivers_fail; + bus_add_attrs(bus); - pr_debug("bus type '%s' registered\n",bus->name); + pr_debug("bus type '%s' registered\n", bus->name); return 0; bus_drivers_fail: @@ -596,7 +665,7 @@ out: /** - * bus_unregister - remove a bus from the system + * bus_unregister - remove a bus from the system * @bus: bus. * * Unregister the child subsystems and the bus itself. @@ -604,7 +673,8 @@ out: */ void bus_unregister(struct bus_type * bus) { - pr_debug("bus %s: unregistering\n",bus->name); + pr_debug("bus %s: unregistering\n", bus->name); + bus_remove_attrs(bus); kset_unregister(&bus->drivers); kset_unregister(&bus->devices); subsystem_unregister(&bus->subsys); diff --git a/drivers/base/class.c b/drivers/base/class.c index ed13d9de0d1d..2693bb5455f4 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -5,7 +5,7 @@ * Copyright (c) 2002-3 Open Source Development Labs * Copyright (c) 2003-2004 Greg Kroah-Hartman * Copyright (c) 2003-2004 IBM Corp. - * + * * This file is released under the GPLv2 * */ @@ -17,8 +17,8 @@ #include <linux/string.h> #include "base.h" -#define to_class_attr(_attr) container_of(_attr,struct class_attribute,attr) -#define to_class(obj) container_of(obj,struct class,subsys.kset.kobj) +#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) +#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj) static ssize_t class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) @@ -28,12 +28,12 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) ssize_t ret = 0; if (class_attr->show) - ret = class_attr->show(dc,buf); + ret = class_attr->show(dc, buf); return ret; } static ssize_t -class_attr_store(struct kobject * kobj, struct attribute * attr, +class_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct class_attribute * class_attr = to_class_attr(attr); @@ -41,7 +41,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (class_attr->store) - ret = class_attr->store(dc,buf,count); + ret = class_attr->store(dc, buf, count); return ret; } @@ -69,14 +69,14 @@ static struct kobj_type ktype_class = { }; /* Hotplug events for classes go to the class_obj subsys */ -static decl_subsys(class,&ktype_class,NULL); +static decl_subsys(class, &ktype_class, NULL); int class_create_file(struct class * cls, const struct class_attribute * attr) { int error; if (cls) { - error = sysfs_create_file(&cls->subsys.kset.kobj,&attr->attr); + error = sysfs_create_file(&cls->subsys.kset.kobj, &attr->attr); } else error = -EINVAL; return error; @@ -85,13 +85,13 @@ int class_create_file(struct class * cls, const struct class_attribute * attr) void class_remove_file(struct class * cls, const struct class_attribute * attr) { if (cls) - sysfs_remove_file(&cls->subsys.kset.kobj,&attr->attr); + sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr); } struct class * class_get(struct class * cls) { if (cls) - return container_of(subsys_get(&cls->subsys),struct class,subsys); + return container_of(subsys_get(&cls->subsys), struct class, subsys); return NULL; } @@ -100,33 +100,67 @@ void class_put(struct class * cls) subsys_put(&cls->subsys); } + +static int add_class_attrs(struct class * cls) +{ + int i; + int error = 0; + + if (cls->class_attrs) { + for (i = 0; attr_name(cls->class_attrs[i]); i++) { + error = class_create_file(cls,&cls->class_attrs[i]); + if (error) + goto Err; + } + } + Done: + return error; + Err: + while (--i >= 0) + class_remove_file(cls,&cls->class_attrs[i]); + goto Done; +} + +static void remove_class_attrs(struct class * cls) +{ + int i; + + if (cls->class_attrs) { + for (i = 0; attr_name(cls->class_attrs[i]); i++) + class_remove_file(cls,&cls->class_attrs[i]); + } +} + int class_register(struct class * cls) { int error; - pr_debug("device class '%s': registering\n",cls->name); + pr_debug("device class '%s': registering\n", cls->name); INIT_LIST_HEAD(&cls->children); INIT_LIST_HEAD(&cls->interfaces); - error = kobject_set_name(&cls->subsys.kset.kobj,cls->name); + error = kobject_set_name(&cls->subsys.kset.kobj, cls->name); if (error) return error; - subsys_set_kset(cls,class_subsys); + subsys_set_kset(cls, class_subsys); error = subsystem_register(&cls->subsys); - if (error) - return error; - - return 0; + if (!error) { + error = add_class_attrs(class_get(cls)); + class_put(cls); + } + return error; } void class_unregister(struct class * cls) { - pr_debug("device class '%s': unregistering\n",cls->name); + pr_debug("device class '%s': unregistering\n", cls->name); + remove_class_attrs(cls); subsystem_unregister(&cls->subsys); } + /* Class Device Stuff */ int class_device_create_file(struct class_device * class_dev, @@ -181,12 +215,12 @@ class_device_attr_show(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (class_dev_attr->show) - ret = class_dev_attr->show(cd,buf); + ret = class_dev_attr->show(cd, buf); return ret; } static ssize_t -class_device_attr_store(struct kobject * kobj, struct attribute * attr, +class_device_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr); @@ -194,7 +228,7 @@ class_device_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (class_dev_attr->store) - ret = class_dev_attr->store(cd,buf,count); + ret = class_dev_attr->store(cd, buf, count); return ret; } @@ -208,7 +242,7 @@ static void class_dev_release(struct kobject * kobj) struct class_device *cd = to_class_dev(kobj); struct class * cls = cd->class; - pr_debug("device class '%s': release.\n",cd->class_id); + pr_debug("device class '%s': release.\n", cd->class_id); if (cls->release) cls->release(cd); @@ -272,6 +306,40 @@ static struct kset_hotplug_ops class_hotplug_ops = { static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops); + +static int class_device_add_attrs(struct class_device * cd) +{ + int i; + int error = 0; + struct class * cls = cd->class; + + if (cls->class_dev_attrs) { + for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) { + error = class_device_create_file(cd, + &cls->class_dev_attrs[i]); + if (error) + goto Err; + } + } + Done: + return error; + Err: + while (--i >= 0) + class_device_remove_file(cd,&cls->class_dev_attrs[i]); + goto Done; +} + +static void class_device_remove_attrs(struct class_device * cd) +{ + int i; + struct class * cls = cd->class; + + if (cls->class_dev_attrs) { + for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) + class_device_remove_file(cd,&cls->class_dev_attrs[i]); + } +} + void class_device_initialize(struct class_device *class_dev) { kobj_set_kset_s(class_dev, class_obj_subsys); @@ -311,7 +379,7 @@ int class_device_add(struct class_device *class_dev) class_intf->add(class_dev); up_write(&parent->subsys.rwsem); } - + class_device_add_attrs(class_dev); class_device_dev_link(class_dev); class_device_driver_link(class_dev); @@ -344,7 +412,8 @@ void class_device_del(struct class_device *class_dev) class_device_dev_unlink(class_dev); class_device_driver_unlink(class_dev); - + class_device_remove_attrs(class_dev); + kobject_del(&class_dev->kobj); if (parent) diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c index 20707be0dcd7..3410636de0a5 100644 --- a/drivers/base/class_simple.c +++ b/drivers/base/class_simple.c @@ -3,7 +3,7 @@ * * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> * Copyright (c) 2003-2004 IBM Corp. - * + * * This file is released under the GPLv2 * */ @@ -111,7 +111,7 @@ EXPORT_SYMBOL(class_simple_destroy); /** * class_simple_device_add - adds a class device to sysfs for a character driver - * @cs: pointer to the struct class_simple that this device should be registered to. + * @cs: pointer to the struct class_simple that this device should be registered to. * @dev: the dev_t for the device to be added. * @device: a pointer to a struct device that is assiociated with this class device. * @fmt: string for the class device's name @@ -146,8 +146,8 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, s_dev->dev = dev; s_dev->class_dev.dev = device; s_dev->class_dev.class = &cs->class; - - va_start(args,fmt); + + va_start(args, fmt); vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args); va_end(args); retval = class_device_register(&s_dev->class_dev); @@ -173,10 +173,10 @@ EXPORT_SYMBOL(class_simple_device_add); * @cs: pointer to the struct class_simple to hold the pointer * @hotplug: function pointer to the hotplug function * - * Implement and set a hotplug function to add environment variables specific to this + * Implement and set a hotplug function to add environment variables specific to this * class on the hotplug event. */ -int class_simple_set_hotplug(struct class_simple *cs, +int class_simple_set_hotplug(struct class_simple *cs, int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size)) { if ((cs == NULL) || (IS_ERR(cs))) diff --git a/drivers/base/core.c b/drivers/base/core.c index 0eaa2c003e69..3325810c42ab 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3,7 +3,7 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * */ @@ -28,8 +28,8 @@ int (*platform_notify_remove)(struct device * dev) = NULL; * sysfs bindings for devices. */ -#define to_dev(obj) container_of(obj,struct device,kobj) -#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr) +#define to_dev(obj) container_of(obj, struct device, kobj) +#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) extern struct attribute * dev_default_attrs[]; @@ -41,12 +41,12 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) ssize_t ret = 0; if (dev_attr->show) - ret = dev_attr->show(dev,buf); + ret = dev_attr->show(dev, buf); return ret; } static ssize_t -dev_attr_store(struct kobject * kobj, struct attribute * attr, +dev_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct device_attribute * dev_attr = to_dev_attr(attr); @@ -54,7 +54,7 @@ dev_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (dev_attr->store) - ret = dev_attr->store(dev,buf,count); + ret = dev_attr->store(dev, buf, count); return ret; } @@ -153,7 +153,7 @@ int device_create_file(struct device * dev, struct device_attribute * attr) { int error = 0; if (get_device(dev)) { - error = sysfs_create_file(&dev->kobj,&attr->attr); + error = sysfs_create_file(&dev->kobj, &attr->attr); put_device(dev); } return error; @@ -168,7 +168,7 @@ int device_create_file(struct device * dev, struct device_attribute * attr) void device_remove_file(struct device * dev, struct device_attribute * attr) { if (get_device(dev)) { - sysfs_remove_file(&dev->kobj,&attr->attr); + sysfs_remove_file(&dev->kobj, &attr->attr); put_device(dev); } } @@ -179,7 +179,7 @@ void device_remove_file(struct device * dev, struct device_attribute * attr) * @dev: device. * * This prepares the device for use by other layers, - * including adding it to the device hierarchy. + * including adding it to the device hierarchy. * It is the first half of device_register(), if called by * that, though it can also be called separately, so one * may use @dev's fields (e.g. the refcount). @@ -187,7 +187,7 @@ void device_remove_file(struct device * dev, struct device_attribute * attr) void device_initialize(struct device *dev) { - kobj_set_kset_s(dev,devices_subsys); + kobj_set_kset_s(dev, devices_subsys); kobject_init(&dev->kobj); INIT_LIST_HEAD(&dev->node); INIT_LIST_HEAD(&dev->children); @@ -200,7 +200,7 @@ void device_initialize(struct device *dev) * device_add - add device to device hierarchy. * @dev: device. * - * This is part 2 of device_register(), though may be called + * This is part 2 of device_register(), though may be called * separately _iff_ device_initialize() has been called separately. * * This adds it to the kobject hierarchy via kobject_add(), adds it @@ -221,7 +221,7 @@ int device_add(struct device *dev) pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); /* first, register with generic layer. */ - kobject_set_name(&dev->kobj,dev->bus_id); + kobject_set_name(&dev->kobj, dev->bus_id); if (parent) dev->kobj.parent = &parent->kobj; @@ -233,7 +233,7 @@ int device_add(struct device *dev) goto BusError; down_write(&devices_subsys.rwsem); if (parent) - list_add_tail(&dev->node,&parent->children); + list_add_tail(&dev->node, &parent->children); up_write(&devices_subsys.rwsem); /* notify platform of device entry */ @@ -245,7 +245,7 @@ int device_add(struct device *dev) BusError: device_pm_remove(dev); PMError: - kobject_unregister(&dev->kobj); + kobject_del(&dev->kobj); Error: if (parent) put_device(parent); @@ -258,9 +258,9 @@ int device_add(struct device *dev) * @dev: pointer to the device structure * * This happens in two clean steps - initialize the device - * and add it to the system. The two steps can be called - * separately, but this is the easiest and most common. - * I.e. you should only call the two helpers separately if + * and add it to the system. The two steps can be called + * separately, but this is the easiest and most common. + * I.e. you should only call the two helpers separately if * have a clearly defined need to use and refcount the device * before it is added to the hierarchy. */ @@ -301,13 +301,13 @@ void put_device(struct device * dev) * device_del - delete device from system. * @dev: device. * - * This is the first part of the device unregistration + * This is the first part of the device unregistration * sequence. This removes the device from the lists we control - * from here, has it removed from the other driver model + * from here, has it removed from the other driver model * subsystems it was added to in device_add(), and removes it * from the kobject hierarchy. * - * NOTE: this should be called manually _iff_ device_add() was + * NOTE: this should be called manually _iff_ device_add() was * also called manually. */ @@ -340,7 +340,7 @@ void device_del(struct device * dev) * we remove it from all the subsystems with device_del(), then * we decrement the reference count via put_device(). If that * is the final reference count, the device will be cleaned up - * via device_release() above. Otherwise, the structure will + * via device_release() above. Otherwise, the structure will * stick around until the final reference to the device is dropped. */ void device_unregister(struct device * dev) @@ -358,7 +358,7 @@ void device_unregister(struct device * dev) * @fn: function to be called for each device. * * Iterate over @dev's child devices, and call @fn for each, - * passing it @data. + * passing it @data. * * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. @@ -370,8 +370,8 @@ int device_for_each_child(struct device * dev, void * data, int error = 0; down_read(&devices_subsys.rwsem); - list_for_each_entry(child,&dev->children,node) { - if((error = fn(child,data))) + list_for_each_entry(child, &dev->children, node) { + if((error = fn(child, data))) break; } up_read(&devices_subsys.rwsem); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 0236ba33542b..0604b2b20e6f 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -3,7 +3,7 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * */ @@ -15,8 +15,8 @@ #include <linux/string.h> #include "base.h" -#define to_dev(node) container_of(node,struct device,driver_list) -#define to_drv(obj) container_of(obj,struct device_driver,kobj) +#define to_dev(node) container_of(node, struct device, driver_list) +#define to_drv(obj) container_of(obj, struct device_driver, kobj) /** * driver_create_file - create sysfs file for driver. @@ -28,7 +28,7 @@ int driver_create_file(struct device_driver * drv, struct driver_attribute * att { int error; if (get_driver(drv)) { - error = sysfs_create_file(&drv->kobj,&attr->attr); + error = sysfs_create_file(&drv->kobj, &attr->attr); put_driver(drv); } else error = -EINVAL; @@ -45,7 +45,7 @@ int driver_create_file(struct device_driver * drv, struct driver_attribute * att void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) { if (get_driver(drv)) { - sysfs_remove_file(&drv->kobj,&attr->attr); + sysfs_remove_file(&drv->kobj, &attr->attr); put_driver(drv); } } @@ -76,7 +76,7 @@ void put_driver(struct device_driver * drv) * @drv: driver to register * * We pass off most of the work to the bus_add_driver() call, - * since most of the things we have to do deal with the bus + * since most of the things we have to do deal with the bus * structures. * * The one interesting aspect is that we initialize @drv->unload_sem @@ -99,8 +99,8 @@ int driver_register(struct device_driver * drv) * * Though, once that is done, we attempt to take @drv->unload_sem. * This will block until the driver refcount reaches 0, and it is - * released. Only modular drivers will call this function, and we - * have to guarantee that it won't complete, letting the driver + * released. Only modular drivers will call this function, and we + * have to guarantee that it won't complete, letting the driver * unload until all references are gone. */ diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c index 886d4961498b..0cff0498ea8b 100644 --- a/drivers/base/firmware.c +++ b/drivers/base/firmware.c @@ -3,7 +3,7 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * */ @@ -12,11 +12,11 @@ #include <linux/module.h> #include <linux/init.h> -static decl_subsys(firmware,NULL,NULL); +static decl_subsys(firmware, NULL, NULL); int firmware_register(struct subsystem * s) { - kset_set_kset_s(s,firmware_subsys); + kset_set_kset_s(s, firmware_subsys); return subsystem_register(s); } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8ff239f146cf..a57ba84eb2c6 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -68,7 +68,7 @@ firmware_timeout_show(struct class *class, char *buf) * firmware will be provided. * * Note: zero means 'wait for ever' - * + * **/ static ssize_t firmware_timeout_store(struct class *class, const char *buf, size_t count) @@ -121,7 +121,7 @@ firmware_loading_show(struct class_device *class_dev, char *buf) /** * firmware_loading_store: - loading control file * Description: - * The relevant values are: + * The relevant values are: * * 1: Start a load, discarding any previous partial load. * 0: Conclude the load and handle the data to the driver code. @@ -376,7 +376,7 @@ out: return retval; } -/** +/** * request_firmware: - request firmware to hotplug and wait for it * Description: * @firmware will be used to return a firmware image by the name @@ -457,7 +457,7 @@ release_firmware(const struct firmware *fw) /** * register_firmware: - provide a firmware image for later usage - * + * * Description: * Make sure that @data will be available by requesting firmware @name. * @@ -541,7 +541,7 @@ request_firmware_nowait( ret = kernel_thread(request_firmware_work_func, fw_work, CLONE_FS | CLONE_FILES); - + if (ret < 0) { fw_work->cont(NULL, fw_work->context); return ret; diff --git a/drivers/base/init.c b/drivers/base/init.c index fd53f364b1ed..7b86c409c648 100644 --- a/drivers/base/init.c +++ b/drivers/base/init.c @@ -2,7 +2,7 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * */ @@ -33,7 +33,7 @@ void __init driver_init(void) classes_init(); firmware_init(); - /* These are also core pieces, but must come after the + /* These are also core pieces, but must come after the * core core pieces. */ platform_bus_init(); diff --git a/drivers/base/interface.c b/drivers/base/interface.c index 1e2d4c328ed5..bd515843a0cb 100644 --- a/drivers/base/interface.c +++ b/drivers/base/interface.c @@ -1,10 +1,10 @@ /* - * drivers/base/interface.c - common driverfs interface that's exported to + * drivers/base/interface.c - common driverfs interface that's exported to * the world for all devices. * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * */ @@ -16,33 +16,33 @@ /** * detach_state - control the default power state for the device. - * - * This is the state the device enters when it's driver module is + * + * This is the state the device enters when it's driver module is * unloaded. The value is an unsigned integer, in the range of 0-4. * '0' indicates 'On', so no action will be taken when the driver is * unloaded. This is the default behavior. * '4' indicates 'Off', meaning the driver core will call the driver's * shutdown method to quiesce the device. - * 1-3 indicate a low-power state for the device to enter via the - * driver's suspend method. + * 1-3 indicate a low-power state for the device to enter via the + * driver's suspend method. */ static ssize_t detach_show(struct device * dev, char * buf) { - return sprintf(buf,"%u\n",dev->detach_state); + return sprintf(buf, "%u\n", dev->detach_state); } static ssize_t detach_store(struct device * dev, const char * buf, size_t n) { u32 state; - state = simple_strtoul(buf,NULL,10); + state = simple_strtoul(buf, NULL, 10); if (state > 4) return -EINVAL; dev->detach_state = state; return n; } -static DEVICE_ATTR(detach_state,0644,detach_show,detach_store); +static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store); struct attribute * dev_default_attrs[] = { diff --git a/drivers/base/node.c b/drivers/base/node.c index b5aa9dc6cdb7..fa06de092972 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -29,7 +29,7 @@ static ssize_t node_read_cpumap(struct sys_device * dev, char * buf) return len; } -static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL); +static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL); /* Can be overwritten by architecture specific code. */ int __attribute__((weak)) hugetlb_report_node_meminfo(int node, char *buf) @@ -54,17 +54,17 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) "Node %d LowFree: %8lu kB\n", nid, K(i.totalram), nid, K(i.freeram), - nid, K(i.totalram-i.freeram), + nid, K(i.totalram - i.freeram), nid, K(i.totalhigh), nid, K(i.freehigh), - nid, K(i.totalram-i.totalhigh), - nid, K(i.freeram-i.freehigh)); + nid, K(i.totalram - i.totalhigh), + nid, K(i.freeram - i.freehigh)); n += hugetlb_report_node_meminfo(nid, buf + n); return n; } -#undef K -static SYSDEV_ATTR(meminfo,S_IRUGO,node_read_meminfo,NULL); +#undef K +static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); static ssize_t node_read_numastat(struct sys_device * dev, char * buf) { @@ -104,7 +104,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) local_node, other_node); } -static SYSDEV_ATTR(numastat,S_IRUGO,node_read_numastat,NULL); +static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); /* * register_node - Setup a driverfs device for a node. diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0d75909a4538..dcb875e487d2 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -3,7 +3,7 @@ * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs - * + * * This file is released under the GPLv2 * * Please see Documentation/driver-model/platform.txt for more @@ -19,12 +19,71 @@ struct device platform_bus = { }; /** + * platform_get_resource - get a resource for a device + * @dev: platform device + * @type: resource type + * @num: resource index + */ +struct resource * +platform_get_resource(struct platform_device *dev, unsigned int type, + unsigned int num) +{ + int i; + + for (i = 0; i < dev->num_resources; i++) { + struct resource *r = &dev->resource[i]; + + if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| + IORESOURCE_IRQ|IORESOURCE_DMA)) + == type) + if (num-- == 0) + return r; + } + return NULL; +} + +/** + * platform_get_irq - get an IRQ for a device + * @dev: platform device + * @num: IRQ number index + */ +int platform_get_irq(struct platform_device *dev, unsigned int num) +{ + struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); + + return r ? r->start : 0; +} + +/** + * platform_add_devices - add a numbers of platform devices + * @devs: array of platform devices to add + * @num: number of platform devices in array + */ +int platform_add_devices(struct platform_device **devs, int num) +{ + int i, ret = 0; + + for (i = 0; i < num; i++) { + ret = platform_device_register(devs[i]); + if (ret) { + while (--i >= 0) + platform_device_unregister(devs[i]); + break; + } + } + + return ret; +} + +/** * platform_device_register - add a platform-level device * @dev: platform device we're adding * */ int platform_device_register(struct platform_device * pdev) { + int i, ret = 0; + if (!pdev) return -EINVAL; @@ -32,18 +91,59 @@ int platform_device_register(struct platform_device * pdev) pdev->dev.parent = &platform_bus; pdev->dev.bus = &platform_bus_type; - - snprintf(pdev->dev.bus_id,BUS_ID_SIZE,"%s%u",pdev->name,pdev->id); + + if (pdev->id != -1) + snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s%u", pdev->name, pdev->id); + else + strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); + + for (i = 0; i < pdev->num_resources; i++) { + struct resource *p, *r = &pdev->resource[i]; + + r->name = pdev->dev.bus_id; + + p = NULL; + if (r->flags & IORESOURCE_MEM) + p = &iomem_resource; + else if (r->flags & IORESOURCE_IO) + p = &ioport_resource; + + if (p && request_resource(p, r)) { + printk(KERN_ERR + "%s: failed to claim resource %d\n", + pdev->dev.bus_id, i); + ret = -EBUSY; + goto failed; + } + } pr_debug("Registering platform device '%s'. Parent at %s\n", - pdev->dev.bus_id,pdev->dev.parent->bus_id); - return device_register(&pdev->dev); + pdev->dev.bus_id, pdev->dev.parent->bus_id); + + ret = device_register(&pdev->dev); + if (ret == 0) + return ret; + + failed: + while (--i >= 0) + if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO)) + release_resource(&pdev->resource[i]); + return ret; } void platform_device_unregister(struct platform_device * pdev) { - if (pdev) + int i; + + if (pdev) { device_unregister(&pdev->dev); + + for (i = 0; i < pdev->num_resources; i++) { + struct resource *r = &pdev->resource[i]; + if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) + release_resource(r); + } + } } @@ -52,13 +152,13 @@ void platform_device_unregister(struct platform_device * pdev) * @dev: device. * @drv: driver. * - * Platform device IDs are assumed to be encoded like this: - * "<name><instance>", where <name> is a short description of the - * type of device, like "pci" or "floppy", and <instance> is the + * Platform device IDs are assumed to be encoded like this: + * "<name><instance>", where <name> is a short description of the + * type of device, like "pci" or "floppy", and <instance> is the * enumerated instance of the device, like '0' or '42'. - * Driver IDs are simply "<name>". - * So, extract the <name> from the platform_device structure, - * and compare it against the name of the driver. Return whether + * Driver IDs are simply "<name>". + * So, extract the <name> from the platform_device structure, + * and compare it against the name of the driver. Return whether * they match or not. */ @@ -114,3 +214,5 @@ EXPORT_SYMBOL(platform_bus); EXPORT_SYMBOL(platform_bus_type); EXPORT_SYMBOL(platform_device_register); EXPORT_SYMBOL(platform_device_unregister); +EXPORT_SYMBOL(platform_get_irq); +EXPORT_SYMBOL(platform_get_resource); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 634c98f5c437..635ea200132e 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -12,10 +12,10 @@ * and add it to the list of power-controlled devices. sysfs entries for * controlling device power management will also be added. * - * A different set of lists than the global subsystem list are used to - * keep track of power info because we use different lists to hold - * devices based on what stage of the power management process they - * are in. The power domain dependencies may also differ from the + * A different set of lists than the global subsystem list are used to + * keep track of power info because we use different lists to hold + * devices based on what stage of the power management process they + * are in. The power domain dependencies may also differ from the * ancestral dependencies that the subsystem list maintains. */ @@ -74,10 +74,10 @@ int device_pm_add(struct device * dev) pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); - atomic_set(&dev->power.pm_users,0); + atomic_set(&dev->power.pm_users, 0); down(&dpm_sem); - list_add_tail(&dev->power.entry,&dpm_active); - device_pm_set_parent(dev,dev->parent); + list_add_tail(&dev->power.entry, &dpm_active); + device_pm_set_parent(dev, dev->parent); if ((error = dpm_sysfs_add(dev))) list_del(&dev->power.entry); up(&dpm_sem); diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index b930ccef5785..6971cc667b17 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -27,7 +27,7 @@ extern void device_shutdown(void); */ extern struct semaphore dpm_sem; -/* +/* * The PM lists. */ extern struct list_head dpm_active; @@ -37,12 +37,12 @@ extern struct list_head dpm_off_irq; static inline struct dev_pm_info * to_pm_info(struct list_head * entry) { - return container_of(entry,struct dev_pm_info,entry); + return container_of(entry, struct dev_pm_info, entry); } static inline struct device * to_device(struct list_head * entry) { - return container_of(to_pm_info(entry),struct device,power); + return container_of(to_pm_info(entry), struct device, power); } extern int device_pm_add(struct device *); @@ -56,7 +56,7 @@ extern int dpm_sysfs_add(struct device *); extern void dpm_sysfs_remove(struct device *); /* - * resume.c + * resume.c */ extern void dpm_resume(void); diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 21d4b56debe0..1d830be4c9bc 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -39,7 +39,7 @@ void dpm_resume(void) if (!dev->power.prev_state) resume_device(dev); - list_add_tail(entry,&dpm_active); + list_add_tail(entry, &dpm_active); } } @@ -48,7 +48,7 @@ void dpm_resume(void) * device_resume - Restore state of each device in system. * * Walk the dpm_off list, remove each entry, resume the device, - * then add it to the dpm_active list. + * then add it to the dpm_active list. */ void device_resume(void) @@ -62,14 +62,14 @@ EXPORT_SYMBOL(device_resume); /** - * device_power_up_irq - Power on some devices. + * device_power_up_irq - Power on some devices. * - * Walk the dpm_off_irq list and power each device up. This + * Walk the dpm_off_irq list and power each device up. This * is used for devices that required they be powered down with * interrupts disabled. As devices are powered on, they are moved to * the dpm_suspended list. * - * Interrupts must be disabled when calling this. + * Interrupts must be disabled when calling this. */ void dpm_power_up(void) @@ -78,7 +78,7 @@ void dpm_power_up(void) struct list_head * entry = dpm_off_irq.next; list_del_init(entry); resume_device(to_device(entry)); - list_add_tail(entry,&dpm_active); + list_add_tail(entry, &dpm_active); } } diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 4ff5340e90fb..5e58f68363af 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -24,9 +24,9 @@ static void runtime_resume(struct device * dev) * dpm_runtime_resume - Power one device back on. * @dev: Device. * - * Bring one device back to the on state by first powering it + * Bring one device back to the on state by first powering it * on, then restoring state. We only operate on devices that aren't - * already on. + * already on. * FIXME: We need to handle devices that are in an unknown state. */ @@ -55,7 +55,7 @@ int dpm_runtime_suspend(struct device * dev, u32 state) if (dev->power.power_state) runtime_resume(dev); - if (!(error = suspend_device(dev,state))) + if (!(error = suspend_device(dev, state))) dev->power.power_state = state; Done: up(&dpm_sem); @@ -70,7 +70,7 @@ int dpm_runtime_suspend(struct device * dev, u32 state) * * This is an update mechanism for drivers to notify the core * what power state a device is in. Device probing code may not - * always be able to tell, but we need accurate information to + * always be able to tell, but we need accurate information to * work reliably. */ void dpm_set_power_state(struct device * dev, u32 state) diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index 6725ffacb518..d1e023fbe169 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c @@ -1,9 +1,9 @@ /* * shutdown.c - power management functions for the device tree. - * + * * Copyright (c) 2002-3 Patrick Mochel * 2002-3 Open Source Development Lab - * + * * This file is released under the GPLv2 * */ @@ -14,7 +14,7 @@ #include "power.h" -#define to_dev(node) container_of(node,struct device,kobj.entry) +#define to_dev(node) container_of(node, struct device, kobj.entry) extern struct subsystem devices_subsys; @@ -29,7 +29,7 @@ int device_detach_shutdown(struct device * dev) dev->driver->shutdown(dev); return 0; } - return dpm_runtime_suspend(dev,dev->detach_state); + return dpm_runtime_suspend(dev, dev->detach_state); } @@ -38,8 +38,8 @@ int device_detach_shutdown(struct device * dev) * down last and resume them first. That way, we don't do anything stupid like * shutting down the interrupt controller before any devices.. * - * Note that there are not different stages for power management calls - - * they only get one called once when interrupts are disabled. + * Note that there are not different stages for power management calls - + * they only get one called once when interrupts are disabled. */ extern int sysdev_shutdown(void); @@ -50,10 +50,10 @@ extern int sysdev_shutdown(void); void device_shutdown(void) { struct device * dev; - + down_write(&devices_subsys.rwsem); - list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) { - pr_debug("shutting down %s: ",dev->bus_id); + list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) { + pr_debug("shutting down %s: ", dev->bus_id); if (dev->driver && dev->driver->shutdown) { pr_debug("Ok\n"); dev->driver->shutdown(dev); diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index a2bc41cc9a38..86f9e6ec05a8 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -1,5 +1,5 @@ /* - * suspend.c - Functions for putting devices to sleep. + * suspend.c - Functions for putting devices to sleep. * * Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Open Source Development Labs @@ -10,18 +10,18 @@ #include <linux/device.h> #include "power.h" - + extern int sysdev_suspend(u32 state); /* * The entries in the dpm_active list are in a depth first order, simply - * because children are guaranteed to be discovered after parents, and - * are inserted at the back of the list on discovery. - * + * because children are guaranteed to be discovered after parents, and + * are inserted at the back of the list on discovery. + * * All list on the suspend path are done in reverse order, so we operate * on the leaves of the device tree (or forests, depending on how you want - * to look at it ;) first. As nodes are removed from the back of the list, - * they are inserted into the front of their destintation lists. + * to look at it ;) first. As nodes are removed from the back of the list, + * they are inserted into the front of their destintation lists. * * Things are the reverse on the resume path - iterations are done in * forward order, and nodes are inserted at the back of their destination @@ -44,7 +44,7 @@ int suspend_device(struct device * dev, u32 state) dev->power.prev_state = dev->power.power_state; if (dev->bus && dev->bus->suspend && !dev->power.power_state) - error = dev->bus->suspend(dev,state); + error = dev->bus->suspend(dev, state); return error; } @@ -52,16 +52,16 @@ int suspend_device(struct device * dev, u32 state) /** * device_suspend - Save state and stop all devices in system. - * @state: Power state to put each device in. + * @state: Power state to put each device in. * * Walk the dpm_active list, call ->suspend() for each device, and move - * it to dpm_off. + * it to dpm_off. * Check the return value for each. If it returns 0, then we move the - * the device to the dpm_off list. If it returns -EAGAIN, we move it to - * the dpm_off_irq list. If we get a different error, try and back out. + * the device to the dpm_off list. If it returns -EAGAIN, we move it to + * the dpm_off_irq list. If we get a different error, try and back out. * * If we hit a failure with any of the devices, call device_resume() - * above to bring the suspended devices back to life. + * above to bring the suspended devices back to life. * * Note this function leaves dpm_sem held to * a) block other devices from registering. @@ -78,14 +78,14 @@ int device_suspend(u32 state) while(!list_empty(&dpm_active)) { struct list_head * entry = dpm_active.prev; struct device * dev = to_device(entry); - error = suspend_device(dev,state); + error = suspend_device(dev, state); if (!error) { list_del(&dev->power.entry); - list_add(&dev->power.entry,&dpm_off); + list_add(&dev->power.entry, &dpm_off); } else if (error == -EAGAIN) { list_del(&dev->power.entry); - list_add(&dev->power.entry,&dpm_off_irq); + list_add(&dev->power.entry, &dpm_off_irq); } else { printk(KERN_ERR "Could not suspend device %s: " "error %d\n", kobject_name(&dev->kobj), error); @@ -108,8 +108,8 @@ EXPORT_SYMBOL(device_suspend); * @state: Power state to enter. * * Walk the dpm_off_irq list, calling ->power_down() for each device that - * couldn't power down the device with interrupts enabled. When we're - * done, power down system devices. + * couldn't power down the device with interrupts enabled. When we're + * done, power down system devices. */ int device_power_down(u32 state) @@ -117,10 +117,10 @@ int device_power_down(u32 state) int error = 0; struct device * dev; - list_for_each_entry_reverse(dev,&dpm_off_irq,power.entry) { - if ((error = suspend_device(dev,state))) + list_for_each_entry_reverse(dev, &dpm_off_irq, power.entry) { + if ((error = suspend_device(dev, state))) break; - } + } if (error) goto Error; if ((error = sysdev_suspend(state))) diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 683dd59b0bff..6ac96349a8e8 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -11,10 +11,10 @@ * * show() returns the current power state of the device. '0' indicates * the device is on. Other values (1-3) indicate the device is in a low - * power state. + * power state. * - * store() sets the current power state, which is an integer value - * between 0-3. If the device is on ('0'), and the value written is + * store() sets the current power state, which is an integer value + * between 0-3. If the device is on ('0'), and the value written is * greater than 0, then the device is placed directly into the low-power * state (via its driver's ->suspend() method). * If the device is currently in a low-power state, and the value is 0, @@ -26,7 +26,7 @@ static ssize_t state_show(struct device * dev, char * buf) { - return sprintf(buf,"%u\n",dev->power.power_state); + return sprintf(buf, "%u\n", dev->power.power_state); } static ssize_t state_store(struct device * dev, const char * buf, size_t n) @@ -35,17 +35,17 @@ static ssize_t state_store(struct device * dev, const char * buf, size_t n) char * rest; int error = 0; - state = simple_strtoul(buf,&rest,10); + state = simple_strtoul(buf, &rest, 10); if (*rest) return -EINVAL; if (state) - error = dpm_runtime_suspend(dev,state); + error = dpm_runtime_suspend(dev, state); else dpm_runtime_resume(dev); return error ? error : n; } -static DEVICE_ATTR(state,0644,state_show,state_store); +static DEVICE_ATTR(state, 0644, state_show, state_store); static struct attribute * power_attrs[] = { @@ -59,10 +59,10 @@ static struct attribute_group pm_attr_group = { int dpm_sysfs_add(struct device * dev) { - return sysfs_create_group(&dev->kobj,&pm_attr_group); + return sysfs_create_group(&dev->kobj, &pm_attr_group); } void dpm_sysfs_remove(struct device * dev) { - sysfs_remove_group(&dev->kobj,&pm_attr_group); + sysfs_remove_group(&dev->kobj, &pm_attr_group); } diff --git a/drivers/base/sys.c b/drivers/base/sys.c index b0d55a930855..9d10500cd961 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -5,8 +5,8 @@ * 2002-3 Open Source Development Lab * * This file is released under the GPLv2 - * - * This exports a 'system' bus type. + * + * This exports a 'system' bus type. * By default, a 'sys' bus gets added to the root of the system. There will * always be core system devices. Devices can use sysdev_register() to * add themselves as children of the system bus. @@ -24,31 +24,31 @@ extern struct subsystem devices_subsys; -#define to_sysdev(k) container_of(k,struct sys_device,kobj) -#define to_sysdev_attr(a) container_of(a,struct sysdev_attribute,attr) +#define to_sysdev(k) container_of(k, struct sys_device, kobj) +#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr) -static ssize_t +static ssize_t sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) { struct sys_device * sysdev = to_sysdev(kobj); struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->show) - return sysdev_attr->show(sysdev,buffer); + return sysdev_attr->show(sysdev, buffer); return 0; } static ssize_t -sysdev_store(struct kobject * kobj, struct attribute * attr, +sysdev_store(struct kobject * kobj, struct attribute * attr, const char * buffer, size_t count) { struct sys_device * sysdev = to_sysdev(kobj); struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->store) - return sysdev_attr->store(sysdev,buffer,count); + return sysdev_attr->store(sysdev, buffer, count); return 0; } @@ -64,22 +64,22 @@ static struct kobj_type ktype_sysdev = { int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a) { - return sysfs_create_file(&s->kobj,&a->attr); + return sysfs_create_file(&s->kobj, &a->attr); } void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a) { - sysfs_remove_file(&s->kobj,&a->attr); + sysfs_remove_file(&s->kobj, &a->attr); } EXPORT_SYMBOL(sysdev_create_file); EXPORT_SYMBOL(sysdev_remove_file); -/* - * declare system_subsys +/* + * declare system_subsys */ -decl_subsys(system,&ktype_sysdev,NULL); +decl_subsys(system, &ktype_sysdev, NULL); int sysdev_class_register(struct sysdev_class * cls) { @@ -87,7 +87,7 @@ int sysdev_class_register(struct sysdev_class * cls) kobject_name(&cls->kset.kobj)); INIT_LIST_HEAD(&cls->drivers); cls->kset.subsys = &system_subsys; - kset_set_kset_s(cls,system_subsys); + kset_set_kset_s(cls, system_subsys); return kset_register(&cls->kset); } @@ -109,19 +109,19 @@ static LIST_HEAD(global_drivers); * @cls: Device class driver belongs to. * @drv: Driver. * - * If @cls is valid, then @drv is inserted into @cls->drivers to be + * If @cls is valid, then @drv is inserted into @cls->drivers to be * called on each operation on devices of that class. The refcount - * of @cls is incremented. - * Otherwise, @drv is inserted into global_drivers, and called for + * of @cls is incremented. + * Otherwise, @drv is inserted into global_drivers, and called for * each device. */ -int sysdev_driver_register(struct sysdev_class * cls, +int sysdev_driver_register(struct sysdev_class * cls, struct sysdev_driver * drv) { down_write(&system_subsys.rwsem); if (cls && kset_get(&cls->kset)) { - list_add_tail(&drv->entry,&cls->drivers); + list_add_tail(&drv->entry, &cls->drivers); /* If devices of this class already exist, tell the driver */ if (drv->add) { @@ -130,7 +130,7 @@ int sysdev_driver_register(struct sysdev_class * cls, drv->add(dev); } } else - list_add_tail(&drv->entry,&global_drivers); + list_add_tail(&drv->entry, &global_drivers); up_write(&system_subsys.rwsem); return 0; } @@ -180,12 +180,12 @@ int sysdev_register(struct sys_device * sysdev) /* But make sure we point to the right type for sysfs translation */ sysdev->kobj.ktype = &ktype_sysdev; - error = kobject_set_name(&sysdev->kobj,"%s%d", - kobject_name(&cls->kset.kobj),sysdev->id); + error = kobject_set_name(&sysdev->kobj, "%s%d", + kobject_name(&cls->kset.kobj), sysdev->id); if (error) return error; - pr_debug("Registering sys device '%s'\n",kobject_name(&sysdev->kobj)); + pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); /* Register the object */ error = kobject_register(&sysdev->kobj); @@ -194,18 +194,18 @@ int sysdev_register(struct sys_device * sysdev) struct sysdev_driver * drv; down_write(&system_subsys.rwsem); - /* Generic notification is implicit, because it's that - * code that should have called us. + /* Generic notification is implicit, because it's that + * code that should have called us. */ /* Notify global drivers */ - list_for_each_entry(drv,&global_drivers,entry) { + list_for_each_entry(drv, &global_drivers, entry) { if (drv->add) drv->add(sysdev); } /* Notify class auxillary drivers */ - list_for_each_entry(drv,&cls->drivers,entry) { + list_for_each_entry(drv, &cls->drivers, entry) { if (drv->add) drv->add(sysdev); } @@ -219,12 +219,12 @@ void sysdev_unregister(struct sys_device * sysdev) struct sysdev_driver * drv; down_write(&system_subsys.rwsem); - list_for_each_entry(drv,&global_drivers,entry) { + list_for_each_entry(drv, &global_drivers, entry) { if (drv->remove) drv->remove(sysdev); } - list_for_each_entry(drv,&sysdev->cls->drivers,entry) { + list_for_each_entry(drv, &sysdev->cls->drivers, entry) { if (drv->remove) drv->remove(sysdev); } @@ -241,12 +241,12 @@ void sysdev_unregister(struct sys_device * sysdev) * Loop over each class of system devices, and the devices in each * of those classes. For each device, we call the shutdown method for * each driver registered for the device - the globals, the auxillaries, - * and the class driver. + * and the class driver. * * Note: The list is iterated in reverse order, so that we shut down * child devices before we shut down thier parents. The list ordering * is guaranteed by virtue of the fact that child devices are registered - * after their parents. + * after their parents. */ void sysdev_shutdown(void) @@ -256,25 +256,25 @@ void sysdev_shutdown(void) pr_debug("Shutting Down System Devices\n"); down_write(&system_subsys.rwsem); - list_for_each_entry_reverse(cls,&system_subsys.kset.list, + list_for_each_entry_reverse(cls, &system_subsys.kset.list, kset.kobj.entry) { struct sys_device * sysdev; pr_debug("Shutting down type '%s':\n", kobject_name(&cls->kset.kobj)); - list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) { + list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { struct sysdev_driver * drv; - pr_debug(" %s\n",kobject_name(&sysdev->kobj)); + pr_debug(" %s\n", kobject_name(&sysdev->kobj)); /* Call global drivers first. */ - list_for_each_entry(drv,&global_drivers,entry) { + list_for_each_entry(drv, &global_drivers, entry) { if (drv->shutdown) drv->shutdown(sysdev); } /* Call auxillary drivers next. */ - list_for_each_entry(drv,&cls->drivers,entry) { + list_for_each_entry(drv, &cls->drivers, entry) { if (drv->shutdown) drv->shutdown(sysdev); } @@ -295,7 +295,7 @@ void sysdev_shutdown(void) * We perform an almost identical operation as sys_device_shutdown() * above, though calling ->suspend() instead. Interrupts are disabled * when this called. Devices are responsible for both saving state and - * quiescing or powering down the device. + * quiescing or powering down the device. * * This is only called by the device PM core, so we let them handle * all synchronization. @@ -307,32 +307,32 @@ int sysdev_suspend(u32 state) pr_debug("Suspending System Devices\n"); - list_for_each_entry_reverse(cls,&system_subsys.kset.list, + list_for_each_entry_reverse(cls, &system_subsys.kset.list, kset.kobj.entry) { struct sys_device * sysdev; pr_debug("Suspending type '%s':\n", kobject_name(&cls->kset.kobj)); - list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) { + list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { struct sysdev_driver * drv; - pr_debug(" %s\n",kobject_name(&sysdev->kobj)); + pr_debug(" %s\n", kobject_name(&sysdev->kobj)); /* Call global drivers first. */ - list_for_each_entry(drv,&global_drivers,entry) { + list_for_each_entry(drv, &global_drivers, entry) { if (drv->suspend) - drv->suspend(sysdev,state); + drv->suspend(sysdev, state); } /* Call auxillary drivers next. */ - list_for_each_entry(drv,&cls->drivers,entry) { + list_for_each_entry(drv, &cls->drivers, entry) { if (drv->suspend) - drv->suspend(sysdev,state); + drv->suspend(sysdev, state); } /* Now call the generic one */ if (cls->suspend) - cls->suspend(sysdev,state); + cls->suspend(sysdev, state); } } return 0; @@ -345,7 +345,7 @@ int sysdev_suspend(u32 state) * Similar to sys_device_suspend(), but we iterate the list forwards * to guarantee that parent devices are resumed before their children. * - * Note: Interrupts are disabled when called. + * Note: Interrupts are disabled when called. */ int sysdev_resume(void) @@ -354,28 +354,28 @@ int sysdev_resume(void) pr_debug("Resuming System Devices\n"); - list_for_each_entry(cls,&system_subsys.kset.list,kset.kobj.entry) { + list_for_each_entry(cls, &system_subsys.kset.list, kset.kobj.entry) { struct sys_device * sysdev; pr_debug("Resuming type '%s':\n", kobject_name(&cls->kset.kobj)); - list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) { + list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { struct sysdev_driver * drv; - pr_debug(" %s\n",kobject_name(&sysdev->kobj)); + pr_debug(" %s\n", kobject_name(&sysdev->kobj)); /* First, call the class-specific one */ if (cls->resume) cls->resume(sysdev); /* Call auxillary drivers next. */ - list_for_each_entry(drv,&cls->drivers,entry) { + list_for_each_entry(drv, &cls->drivers, entry) { if (drv->resume) drv->resume(sysdev); } /* Call global drivers. */ - list_for_each_entry(drv,&global_drivers,entry) { + list_for_each_entry(drv, &global_drivers, entry) { if (drv->resume) drv->resume(sysdev); } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 0e18df6b76e5..afb9d4391a7a 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -285,14 +285,14 @@ config BLK_DEV_NBD If unsure, say N. -config BLK_DEV_CARMEL - tristate "Promise SATA SX8 (carmel) support" +config BLK_DEV_SX8 + tristate "Promise SATA SX8 support" depends on PCI ---help--- Saying Y or M here will enable support for the - Promise SATA SX8 ("carmel") controllers. + Promise SATA SX8 controllers. - Use devices /dev/carmel/$N and /dev/carmel/$Np$M. + Use devices /dev/sx8/$N and /dev/sx8/$Np$M. config BLK_DEV_RAM tristate "RAM disk support" diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 33b14e84cd8c..2654b5b7615e 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -41,5 +41,5 @@ obj-$(CONFIG_BLK_DEV_NBD) += nbd.o obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o obj-$(CONFIG_VIODASD) += viodasd.o -obj-$(CONFIG_BLK_DEV_CARMEL) += carmel.o +obj-$(CONFIG_BLK_DEV_SX8) += sx8.o diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 6203e02ad5c2..1ee5ab64f11f 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -2667,7 +2667,7 @@ static int __end_that_request_first(struct request *req, int uptodate, } total_bytes = bio_nbytes = 0; - while ((bio = req->bio)) { + while ((bio = req->bio) != NULL) { int nbytes; if (nr_bytes >= bio->bi_size) { diff --git a/drivers/block/carmel.c b/drivers/block/sx8.c index 38fd6fe42d07..0a0234129030 100644 --- a/drivers/block/carmel.c +++ b/drivers/block/sx8.c @@ -1,5 +1,5 @@ /* - * carmel.c: Driver for Promise SATA SX8 looks-like-I2O hardware + * sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware * * Copyright 2004 Red Hat, Inc. * @@ -32,7 +32,7 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Promise SATA SX8 (carmel) block driver"); +MODULE_DESCRIPTION("Promise SATA SX8 block driver"); #if 0 #define CARM_DEBUG @@ -43,7 +43,7 @@ MODULE_DESCRIPTION("Promise SATA SX8 (carmel) block driver"); #endif #undef CARM_NDEBUG -#define DRV_NAME "carmel" +#define DRV_NAME "sx8" #define DRV_VERSION "0.8" #define PFX DRV_NAME ": " diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 9c19dbc8eb19..b416bdf57080 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -18,6 +18,7 @@ #include <linux/capability.h> #include <linux/uio.h> #include <linux/cdev.h> +#include <linux/device.h> #include <asm/uaccess.h> @@ -26,6 +27,7 @@ struct raw_device_data { int inuse; }; +static struct class_simple *raw_class; static struct raw_device_data raw_devices[MAX_RAW_MINORS]; static DECLARE_MUTEX(raw_mutex); static struct file_operations raw_ctl_fops; /* forward declaration */ @@ -123,6 +125,13 @@ raw_ioctl(struct inode *inode, struct file *filp, return ioctl_by_bdev(bdev, command, arg); } +static void bind_device(struct raw_config_request rq) +{ + class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor)); + class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq.raw_minor), + NULL, "raw%d", rq.raw_minor); +} + /* * Deal with ioctls against the raw-device control interface, to bind * and unbind other raw devices. @@ -191,12 +200,15 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, if (rq.block_major == 0 && rq.block_minor == 0) { /* unbind */ rawdev->binding = NULL; + class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor)); } else { rawdev->binding = bdget(dev); if (rawdev->binding == NULL) err = -ENOMEM; - else + else { __module_get(THIS_MODULE); + bind_device(rq); + } } up(&raw_mutex); } else { @@ -287,6 +299,15 @@ static int __init raw_init(void) goto error; } + raw_class = class_simple_create(THIS_MODULE, "raw"); + if (IS_ERR(raw_class)) { + printk(KERN_ERR "Error creating raw class.\n"); + cdev_del(&raw_cdev); + unregister_chrdev_region(dev, MAX_RAW_MINORS); + goto error; + } + class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); + devfs_mk_cdev(MKDEV(RAW_MAJOR, 0), S_IFCHR | S_IRUGO | S_IWUGO, "raw/rawctl"); @@ -309,6 +330,8 @@ static void __exit raw_exit(void) devfs_remove("raw/raw%d", i); devfs_remove("raw/rawctl"); devfs_remove("raw"); + class_simple_device_remove(MKDEV(RAW_MAJOR, 0)); + class_simple_destroy(raw_class); cdev_del(&raw_cdev); unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); } diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index c2b2dec8009c..703adb11115e 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -96,12 +96,13 @@ config IXP4XX_WATCHDOG Say N if you are unsure. config SA1100_WATCHDOG - tristate "SA1100 watchdog" - depends on WATCHDOG && ARCH_SA1100 + tristate "SA1100/PXA2xx watchdog" + depends on WATCHDOG && ( ARCH_SA1100 || ARCH_PXA ) help - Watchdog timer embedded into SA11x0 chips. This will reboot your - system when timeout is reached. - NOTE, that once enabled, this timer cannot be disabled. + Watchdog timer embedded into SA11x0 and PXA2xx chips. This will + reboot your system when timeout is reached. + + NOTE: once enabled, this timer cannot be disabled. To compile this driver as a module, choose M here: the module will be called sa1100_wdt. diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 862fb9ab344a..aa3901fbab26 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -1,5 +1,5 @@ /* - * Watchdog driver for the SA11x0 + * Watchdog driver for the SA11x0/PXA2xx * * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> * Based on SoftDog driver by Alan Cox <alan@redhat.com> @@ -174,7 +174,7 @@ static struct file_operations sa1100dog_fops = static struct miscdevice sa1100dog_miscdev = { .minor = WATCHDOG_MINOR, - .name = "SA1100 watchdog", + .name = "SA1100/PXA2xx watchdog", .fops = &sa1100dog_fops, }; @@ -194,7 +194,7 @@ static int __init sa1100dog_init(void) ret = misc_register(&sa1100dog_miscdev); if (ret == 0) - printk("SA1100 Watchdog Timer: timer margin %d sec\n", + printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", margin); return ret; @@ -209,7 +209,7 @@ module_init(sa1100dog_init); module_exit(sa1100dog_exit); MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>"); -MODULE_DESCRIPTION("SA1100 Watchdog"); +MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 429070cd8f13..4f92849567aa 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -134,7 +134,7 @@ struct efivar_attribute { #define EFI_ATTR(_name, _mode, _show, _store) \ struct subsys_attribute efi_attr_##_name = { \ - .attr {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ .show = _show, \ .store = _store, \ }; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 31ee54341952..6e22814a7f40 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -138,7 +138,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev)); - if(ibm_dmi_probe()) { + if(ibm_dmi_probe() && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module " "may corrupt your serial eeprom! Refusing to load " "module!\n"); diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c index f93b6f67696e..a416e4ee560e 100644 --- a/drivers/i2c/chips/asb100.c +++ b/drivers/i2c/chips/asb100.c @@ -272,7 +272,7 @@ static ssize_t \ return show_in(dev, buf, 0x##offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in##offset, NULL) \ + show_in##offset, NULL); \ static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ @@ -294,17 +294,17 @@ static ssize_t set_in##offset##_max (struct device *dev, \ return set_in_max(dev, buf, count, 0x##offset); \ } \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min) \ + show_in##offset##_min, set_in##offset##_min); \ static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max) + show_in##offset##_max, set_in##offset##_max); -sysfs_in(0) -sysfs_in(1) -sysfs_in(2) -sysfs_in(3) -sysfs_in(4) -sysfs_in(5) -sysfs_in(6) +sysfs_in(0); +sysfs_in(1); +sysfs_in(2); +sysfs_in(3); +sysfs_in(4); +sysfs_in(5); +sysfs_in(6); #define device_create_file_in(client, offset) do { \ device_create_file(&client->dev, &dev_attr_in##offset##_input); \ @@ -410,15 +410,15 @@ static ssize_t set_fan##offset##_div(struct device *dev, const char *buf, \ return set_fan_div(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan##offset, NULL) \ + show_fan##offset, NULL); \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan##offset##_min, set_fan##offset##_min) \ + show_fan##offset##_min, set_fan##offset##_min); \ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan##offset##_div, set_fan##offset##_div) + show_fan##offset##_div, set_fan##offset##_div); -sysfs_fan(1) -sysfs_fan(2) -sysfs_fan(3) +sysfs_fan(1); +sysfs_fan(2); +sysfs_fan(3); #define device_create_file_fan(client, offset) do { \ device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ @@ -449,9 +449,9 @@ static ssize_t show_##reg(struct device *dev, char *buf, int nr) \ return sprintf_temp_from_reg(data->reg[nr], buf, nr); \ } -show_temp_reg(temp) -show_temp_reg(temp_max) -show_temp_reg(temp_hyst) +show_temp_reg(temp); +show_temp_reg(temp_max); +show_temp_reg(temp_hyst); #define set_temp_reg(REG, reg) \ static ssize_t set_##reg(struct device *dev, const char *buf, \ @@ -473,15 +473,15 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \ return count; \ } -set_temp_reg(MAX, temp_max) -set_temp_reg(HYST, temp_hyst) +set_temp_reg(MAX, temp_max); +set_temp_reg(HYST, temp_hyst); #define sysfs_temp(num) \ static ssize_t show_temp##num(struct device *dev, char *buf) \ { \ return show_temp(dev, buf, num-1); \ } \ -static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL) \ +static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL); \ static ssize_t show_temp_max##num(struct device *dev, char *buf) \ { \ return show_temp_max(dev, buf, num-1); \ @@ -492,7 +492,7 @@ static ssize_t set_temp_max##num(struct device *dev, const char *buf, \ return set_temp_max(dev, buf, count, num-1); \ } \ static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \ - show_temp_max##num, set_temp_max##num) \ + show_temp_max##num, set_temp_max##num); \ static ssize_t show_temp_hyst##num(struct device *dev, char *buf) \ { \ return show_temp_hyst(dev, buf, num-1); \ @@ -503,12 +503,12 @@ static ssize_t set_temp_hyst##num(struct device *dev, const char *buf, \ return set_temp_hyst(dev, buf, count, num-1); \ } \ static DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_hyst##num, set_temp_hyst##num) + show_temp_hyst##num, set_temp_hyst##num); -sysfs_temp(1) -sysfs_temp(2) -sysfs_temp(3) -sysfs_temp(4) +sysfs_temp(1); +sysfs_temp(2); +sysfs_temp(3); +sysfs_temp(4); /* VID */ #define device_create_file_temp(client, num) do { \ @@ -523,7 +523,7 @@ static ssize_t show_vid(struct device *dev, char *buf) return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL) +static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL); #define device_create_file_vid(client) \ device_create_file(&client->dev, &dev_attr_in0_ref) @@ -544,7 +544,7 @@ static ssize_t set_vrm(struct device *dev, const char *buf, size_t count) } /* Alarms */ -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm) +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); #define device_create_file_vrm(client) \ device_create_file(&client->dev, &dev_attr_vrm); @@ -554,7 +554,7 @@ static ssize_t show_alarms(struct device *dev, char *buf) return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms)); } -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL) +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); #define device_create_file_alarms(client) \ device_create_file(&client->dev, &dev_attr_alarms) @@ -594,9 +594,9 @@ static ssize_t set_pwm_enable1(struct device *dev, const char *buf, return count; } -static DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1) +static DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); static DEVICE_ATTR(fan1_pwm_enable, S_IRUGO | S_IWUSR, - show_pwm_enable1, set_pwm_enable1) + show_pwm_enable1, set_pwm_enable1); #define device_create_file_pwm1(client) do { \ device_create_file(&new_client->dev, &dev_attr_fan1_pwm); \ device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); \ diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index 061a0b8009b5..ef656298779a 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -128,15 +128,15 @@ static int reset; #define IT87_REG_FAN(nr) (0x0d + (nr)) #define IT87_REG_FAN_MIN(nr) (0x10 + (nr)) -#define IT87_REG_FAN_CTRL 0x13 +#define IT87_REG_FAN_MAIN_CTRL 0x13 #define IT87_REG_VIN(nr) (0x20 + (nr)) #define IT87_REG_TEMP(nr) (0x29 + (nr)) #define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2) #define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2) -#define IT87_REG_TEMP_HIGH(nr) (0x40 + ((nr) * 2)) -#define IT87_REG_TEMP_LOW(nr) (0x41 + ((nr) * 2)) +#define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2) +#define IT87_REG_TEMP_LOW(nr) (0x41 + (nr) * 2) #define IT87_REG_I2C_ADDR 0x48 @@ -145,8 +145,8 @@ static int reset; #define IT87_REG_CHIPID 0x58 -#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255)) -#define IN_FROM_REG(val) (((val) * 16) / 10) +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) +#define IN_FROM_REG(val) ((val) * 16) static inline u8 FAN_TO_REG(long rpm, int div) { @@ -159,9 +159,9 @@ static inline u8 FAN_TO_REG(long rpm, int div) #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) -#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\ - ((val)+5)/10),0,255)) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ + ((val)+500)/1000),-128,127)) +#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) #define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\ 205-(val)*5) @@ -170,7 +170,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) static int DIV_TO_REG(int val) { int answer = 0; - while ((val >>= 1)) + while ((val >>= 1) != 0) answer++; return answer; } @@ -231,19 +231,19 @@ static int it87_id = 0; static ssize_t show_in(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])*10 ); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])); } static ssize_t show_in_min(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])*10 ); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])); } static ssize_t show_in_max(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])*10 ); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])); } static ssize_t set_in_min(struct device *dev, const char *buf, @@ -251,7 +251,7 @@ static ssize_t set_in_min(struct device *dev, const char *buf, { struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10)/10; + unsigned long val = simple_strtoul(buf, NULL, 10); data->in_min[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MIN(nr), data->in_min[nr]); @@ -262,7 +262,7 @@ static ssize_t set_in_max(struct device *dev, const char *buf, { struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10)/10; + unsigned long val = simple_strtoul(buf, NULL, 10); data->in_max[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MAX(nr), data->in_max[nr]); @@ -275,7 +275,7 @@ static ssize_t \ { \ return show_in(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL) +static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); #define limit_in_offset(offset) \ static ssize_t \ @@ -299,9 +299,9 @@ static ssize_t set_in##offset##_max (struct device *dev, \ return set_in_max(dev, buf, count, 0x##offset); \ } \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min) \ + show_in##offset##_min, set_in##offset##_min); \ static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max) + show_in##offset##_max, set_in##offset##_max); show_in_offset(0); limit_in_offset(0); @@ -325,24 +325,24 @@ show_in_offset(8); static ssize_t show_temp(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 ); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); } static ssize_t show_temp_max(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])); } static ssize_t show_temp_min(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*100); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])); } static ssize_t set_temp_max(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10)/100; + int val = simple_strtol(buf, NULL, 10); data->temp_high[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); return count; @@ -352,7 +352,7 @@ static ssize_t set_temp_min(struct device *dev, const char *buf, { struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10)/100; + int val = simple_strtol(buf, NULL, 10); data->temp_low[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); return count; @@ -382,11 +382,11 @@ static ssize_t set_temp_##offset##_min (struct device *dev, \ { \ return set_temp_min(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \ +static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \ static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_max, set_temp_##offset##_max) \ + show_temp_##offset##_max, set_temp_##offset##_max); \ static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_min, set_temp_##offset##_min) + show_temp_##offset##_min, set_temp_##offset##_min); show_temp_offset(1); show_temp_offset(2); @@ -430,8 +430,8 @@ static ssize_t set_sensor_##offset (struct device *dev, \ { \ return set_sensor(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ - show_sensor_##offset, set_sensor_##offset) +static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ + show_sensor_##offset, set_sensor_##offset); show_sensor_offset(1); show_sensor_offset(2); @@ -525,11 +525,11 @@ static ssize_t set_fan_##offset##_div (struct device *dev, \ { \ return set_fan_div(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \ +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min) \ + show_fan_##offset##_min, set_fan_##offset##_min); \ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_div, set_fan_##offset##_div) + show_fan_##offset##_div, set_fan_##offset##_div); show_fan_offset(1); show_fan_offset(2); @@ -773,9 +773,7 @@ static int it87_detach_client(struct i2c_client *client) We don't want to lock the whole ISA bus, so we lock each client separately. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, - would slow down the IT87 access and should not be necessary. - There are some ugly typecasts here, but the good new is - they should - nowhere else be necessary! */ + would slow down the IT87 access and should not be necessary. */ static int it87_read_value(struct i2c_client *client, u8 reg) { struct it87_data *data = i2c_get_clientdata(client); @@ -795,9 +793,7 @@ static int it87_read_value(struct i2c_client *client, u8 reg) We don't want to lock the whole ISA bus, so we lock each client separately. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, - would slow down the IT87 access and should not be necessary. - There are some ugly typecasts here, but the good new is - they should - nowhere else be necessary! */ + would slow down the IT87 access and should not be necessary. */ static int it87_write_value(struct i2c_client *client, u8 reg, u8 value) { struct it87_data *data = i2c_get_clientdata(client); @@ -840,11 +836,11 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) } /* Check if tachometers are reset manually or by some reason */ - tmp = it87_read_value(client, IT87_REG_FAN_CTRL); + tmp = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); if ((tmp & 0x70) == 0) { /* Enable all fan tachometers */ tmp = (tmp & 0x8f) | 0x70; - it87_write_value(client, IT87_REG_FAN_CTRL, tmp); + it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, tmp); } /* Start monitoring */ diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c index 74a1ca76cc04..b9ffad6c36e4 100644 --- a/drivers/i2c/chips/lm78.c +++ b/drivers/i2c/chips/lm78.c @@ -281,7 +281,7 @@ static ssize_t \ return show_in(dev, buf, 0x##offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in##offset, NULL) \ + show_in##offset, NULL); \ static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ @@ -303,9 +303,9 @@ static ssize_t set_in##offset##_max (struct device *dev, \ return set_in_max(dev, buf, count, 0x##offset); \ } \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min) \ + show_in##offset##_min, set_in##offset##_min); \ static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max) + show_in##offset##_max, set_in##offset##_max); show_in_offset(0); show_in_offset(1); @@ -354,11 +354,11 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count) return count; } -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL) +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp_over, set_temp_over) + show_temp_over, set_temp_over); static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - show_temp_hyst, set_temp_hyst) + show_temp_hyst, set_temp_hyst); /* 3 Fans */ static ssize_t show_fan(struct device *dev, char *buf, int nr) @@ -439,9 +439,9 @@ static ssize_t set_fan_##offset##_min (struct device *dev, \ { \ return set_fan_min(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \ +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min) + show_fan_##offset##_min, set_fan_##offset##_min); static ssize_t set_fan_1_div(struct device *dev, const char *buf, size_t count) @@ -461,10 +461,10 @@ show_fan_offset(3); /* Fan 3 divisor is locked in H/W */ static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - show_fan_1_div, set_fan_1_div) + show_fan_1_div, set_fan_1_div); static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - show_fan_2_div, set_fan_2_div) -static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL) + show_fan_2_div, set_fan_2_div); +static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL); /* VID */ static ssize_t show_vid(struct device *dev, char *buf) diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c index 795852aa6719..11f85043153b 100644 --- a/drivers/i2c/chips/lm85.c +++ b/drivers/i2c/chips/lm85.c @@ -451,9 +451,9 @@ static ssize_t set_fan_##offset##_min (struct device *dev, \ { \ return set_fan_min(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \ +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min) + show_fan_##offset##_min, set_fan_##offset##_min); show_fan_offset(1); show_fan_offset(2); @@ -468,7 +468,7 @@ static ssize_t show_vid_reg(struct device *dev, char *buf) return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL) +static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, char *buf) { @@ -487,7 +487,7 @@ static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count) return count; } -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg) +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); static ssize_t show_alarms_reg(struct device *dev, char *buf) { @@ -495,7 +495,7 @@ static ssize_t show_alarms_reg(struct device *dev, char *buf) return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms)); } -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL) +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); /* pwm */ @@ -542,8 +542,8 @@ static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \ return show_pwm_enable(dev, buf, 0x##offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ - show_pwm_##offset, set_pwm_##offset) \ -static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO, show_pwm_enable##offset, NULL) + show_pwm_##offset, set_pwm_##offset); \ +static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO, show_pwm_enable##offset, NULL); show_pwm_reg(1); show_pwm_reg(2); @@ -617,11 +617,11 @@ static ssize_t set_in_##offset##_max (struct device *dev, \ { \ return set_in_max(dev, buf, count, 0x##offset); \ } \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, NULL) \ +static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, NULL); \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_##offset##_min, set_in_##offset##_min) \ + show_in_##offset##_min, set_in_##offset##_min); \ static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_##offset##_max, set_in_##offset##_max) + show_in_##offset##_max, set_in_##offset##_max); show_in_reg(0); show_in_reg(1); @@ -697,11 +697,11 @@ static ssize_t set_temp_##offset##_max (struct device *dev, \ { \ return set_temp_max(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \ +static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \ static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_min, set_temp_##offset##_min) \ + show_temp_##offset##_min, set_temp_##offset##_min); \ static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_max, set_temp_##offset##_max) + show_temp_##offset##_max, set_temp_##offset##_max); show_temp_reg(1); show_temp_reg(2); diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c index a5ec359b0f6f..3aa334583b89 100644 --- a/drivers/i2c/chips/via686a.c +++ b/drivers/i2c/chips/via686a.c @@ -405,11 +405,11 @@ static ssize_t set_in##offset##_max (struct device *dev, \ { \ return set_in_max(dev, buf, count, 0x##offset); \ } \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL) \ +static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min) \ + show_in##offset##_min, set_in##offset##_min); \ static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max) + show_in##offset##_max, set_in##offset##_max); show_in_offset(0); show_in_offset(1); @@ -473,11 +473,11 @@ static ssize_t set_temp_##offset##_hyst (struct device *dev, \ { \ return set_temp_hyst(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \ +static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\ static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_over, set_temp_##offset##_over) \ + show_temp_##offset##_over, set_temp_##offset##_over); \ static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_hyst, set_temp_##offset##_hyst) + show_temp_##offset##_hyst, set_temp_##offset##_hyst); show_temp_offset(1); show_temp_offset(2); @@ -542,11 +542,11 @@ static ssize_t set_fan_##offset##_div (struct device *dev, \ { \ return set_fan_div(dev, buf, count, 0x##offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \ +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min) \ + show_fan_##offset##_min, set_fan_##offset##_min); \ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_div, set_fan_##offset##_div) + show_fan_##offset##_div, set_fan_##offset##_div); show_fan_offset(1); show_fan_offset(2); diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c index c38a7f9712b6..5d1a31bcb222 100644 --- a/drivers/i2c/chips/w83627hf.c +++ b/drivers/i2c/chips/w83627hf.c @@ -199,7 +199,7 @@ superio_exit(void) #define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ #define W83627THF_REG_PWM3 0x11 /* 637HF too */ -#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too, unused yet */ +#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, @@ -222,7 +222,7 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; these macros are called: arguments may be evaluated more than once. Fixing this is just not worth it. */ #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) -#define IN_FROM_REG(val) ((val) * 16 + 5) +#define IN_FROM_REG(val) ((val) * 16) static inline u8 FAN_TO_REG(long rpm, int div) { @@ -312,6 +312,7 @@ struct w83627hf_data { Default = 3435. Other Betas unimplemented */ u8 vrm; + u8 vrm_ovt; /* Register value, 627thf & 637hf only */ }; @@ -370,7 +371,7 @@ show_regs_in_##offset (struct device *dev, char *buf) \ { \ return show_in(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL) +static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); #define sysfs_in_reg_offset(reg, offset) \ static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \ @@ -384,22 +385,104 @@ store_regs_in_##reg##offset (struct device *dev, \ return store_in_##reg (dev, buf, count, 0x##offset); \ } \ static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, \ - show_regs_in_##reg##offset, store_regs_in_##reg##offset) + show_regs_in_##reg##offset, store_regs_in_##reg##offset); #define sysfs_in_offsets(offset) \ sysfs_in_offset(offset) \ sysfs_in_reg_offset(min, offset) \ sysfs_in_reg_offset(max, offset) -sysfs_in_offsets(0) -sysfs_in_offsets(1) -sysfs_in_offsets(2) -sysfs_in_offsets(3) -sysfs_in_offsets(4) -sysfs_in_offsets(5) -sysfs_in_offsets(6) -sysfs_in_offsets(7) -sysfs_in_offsets(8) +sysfs_in_offsets(1); +sysfs_in_offsets(2); +sysfs_in_offsets(3); +sysfs_in_offsets(4); +sysfs_in_offsets(5); +sysfs_in_offsets(6); +sysfs_in_offsets(7); +sysfs_in_offsets(8); + +/* use a different set of functions for in0 */ +static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) +{ + long in0; + + if ((data->vrm_ovt & 0x01) && + (w83627thf == data->type || w83637hf == data->type)) + + /* use VRM9 calculation */ + in0 = (long)((reg * 488 + 70000 + 50) / 100); + else + /* use VRM8 (standard) calculation */ + in0 = (long)IN_FROM_REG(reg); + + return sprintf(buf,"%ld\n", in0); +} + +static ssize_t show_regs_in_0(struct device *dev, char *buf) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + return show_in_0(data, buf, data->in[0]); +} + +static ssize_t show_regs_in_min0(struct device *dev, char *buf) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + return show_in_0(data, buf, data->in_min[0]); +} + +static ssize_t show_regs_in_max0(struct device *dev, char *buf) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + return show_in_0(data, buf, data->in_max[0]); +} + +static ssize_t store_regs_in_min0(struct device *dev, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83627hf_data *data = i2c_get_clientdata(client); + u32 val; + + val = simple_strtoul(buf, NULL, 10); + if ((data->vrm_ovt & 0x01) && + (w83627thf == data->type || w83637hf == data->type)) + + /* use VRM9 calculation */ + data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488); + else + /* use VRM8 (standard) calculation */ + data->in_min[0] = IN_TO_REG(val); + + w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); + return count; +} + +static ssize_t store_regs_in_max0(struct device *dev, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83627hf_data *data = i2c_get_clientdata(client); + u32 val; + + val = simple_strtoul(buf, NULL, 10); + if ((data->vrm_ovt & 0x01) && + (w83627thf == data->type || w83637hf == data->type)) + + /* use VRM9 calculation */ + data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488); + else + /* use VRM8 (standard) calculation */ + data->in_max[0] = IN_TO_REG(val); + + w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); + return count; +} + +static DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL); +static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, + show_regs_in_min0, store_regs_in_min0); +static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, + show_regs_in_max0, store_regs_in_max0); #define device_create_file_in(client, offset) \ do { \ @@ -416,8 +499,8 @@ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ FAN_FROM_REG(data->reg[nr-1], \ (long)DIV_FROM_REG(data->fan_div[nr-1]))); \ } -show_fan_reg(fan) -show_fan_reg(fan_min) +show_fan_reg(fan); +show_fan_reg(fan_min); static ssize_t store_fan_min(struct device *dev, const char *buf, size_t count, int nr) @@ -440,7 +523,7 @@ static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \ { \ return show_fan(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL) +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); #define sysfs_fan_min_offset(offset) \ static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \ @@ -453,14 +536,14 @@ store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \ return store_fan_min(dev, buf, count, 0x##offset); \ } \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_regs_fan_min##offset, store_regs_fan_min##offset) + show_regs_fan_min##offset, store_regs_fan_min##offset); -sysfs_fan_offset(1) -sysfs_fan_min_offset(1) -sysfs_fan_offset(2) -sysfs_fan_min_offset(2) -sysfs_fan_offset(3) -sysfs_fan_min_offset(3) +sysfs_fan_offset(1); +sysfs_fan_min_offset(1); +sysfs_fan_offset(2); +sysfs_fan_min_offset(2); +sysfs_fan_offset(3); +sysfs_fan_min_offset(3); #define device_create_file_fan(client, offset) \ do { \ @@ -479,9 +562,9 @@ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \ } \ } -show_temp_reg(temp) -show_temp_reg(temp_max) -show_temp_reg(temp_max_hyst) +show_temp_reg(temp); +show_temp_reg(temp_max); +show_temp_reg(temp_max_hyst); #define store_temp_reg(REG, reg) \ static ssize_t \ @@ -505,8 +588,8 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ \ return count; \ } -store_temp_reg(OVER, max) -store_temp_reg(HYST, max_hyst) +store_temp_reg(OVER, max); +store_temp_reg(HYST, max_hyst); #define sysfs_temp_offset(offset) \ static ssize_t \ @@ -514,7 +597,7 @@ show_regs_temp_##offset (struct device *dev, char *buf) \ { \ return show_temp(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL) +static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); #define sysfs_temp_reg_offset(reg, offset) \ static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \ @@ -528,16 +611,16 @@ store_regs_temp_##reg##offset (struct device *dev, \ return store_temp_##reg (dev, buf, count, 0x##offset); \ } \ static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ - show_regs_temp_##reg##offset, store_regs_temp_##reg##offset) + show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); #define sysfs_temp_offsets(offset) \ sysfs_temp_offset(offset) \ sysfs_temp_reg_offset(max, offset) \ sysfs_temp_reg_offset(max_hyst, offset) -sysfs_temp_offsets(1) -sysfs_temp_offsets(2) -sysfs_temp_offsets(3) +sysfs_temp_offsets(1); +sysfs_temp_offsets(2); +sysfs_temp_offsets(3); #define device_create_file_temp(client, offset) \ do { \ @@ -552,7 +635,7 @@ show_vid_reg(struct device *dev, char *buf) struct w83627hf_data *data = w83627hf_update_device(dev); return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL) +static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ device_create_file(&client->dev, &dev_attr_in0_ref) @@ -574,7 +657,7 @@ store_vrm_reg(struct device *dev, const char *buf, size_t count) return count; } -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg) +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); #define device_create_file_vrm(client) \ device_create_file(&client->dev, &dev_attr_vrm) @@ -584,7 +667,7 @@ show_alarms_reg(struct device *dev, char *buf) struct w83627hf_data *data = w83627hf_update_device(dev); return sprintf(buf, "%ld\n", (long) data->alarms); } -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL) +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); #define device_create_file_alarms(client) \ device_create_file(&client->dev, &dev_attr_alarms) @@ -641,10 +724,10 @@ store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \ return store_beep_reg(dev, buf, count, BEEP_##REG); \ } \ static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \ - show_regs_beep_##reg, store_regs_beep_##reg) + show_regs_beep_##reg, store_regs_beep_##reg); -sysfs_beep(ENABLE, enable) -sysfs_beep(MASK, mask) +sysfs_beep(ENABLE, enable); +sysfs_beep(MASK, mask); #define device_create_file_beep(client) \ do { \ @@ -707,11 +790,11 @@ store_regs_fan_div_##offset (struct device *dev, \ return store_fan_div_reg(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_regs_fan_div_##offset, store_regs_fan_div_##offset) + show_regs_fan_div_##offset, store_regs_fan_div_##offset); -sysfs_fan_div(1) -sysfs_fan_div(2) -sysfs_fan_div(3) +sysfs_fan_div(1); +sysfs_fan_div(2); +sysfs_fan_div(3); #define device_create_file_fan_div(client, offset) \ do { \ @@ -763,11 +846,11 @@ store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \ return store_pwm_reg(dev, buf, count, offset); \ } \ static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ - show_regs_pwm_##offset, store_regs_pwm_##offset) + show_regs_pwm_##offset, store_regs_pwm_##offset); -sysfs_pwm(1) -sysfs_pwm(2) -sysfs_pwm(3) +sysfs_pwm(1); +sysfs_pwm(2); +sysfs_pwm(3); #define device_create_file_pwm(client, offset) \ do { \ @@ -836,11 +919,11 @@ store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \ return store_sensor_reg(dev, buf, count, offset); \ } \ static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ - show_regs_sensor_##offset, store_regs_sensor_##offset) + show_regs_sensor_##offset, store_regs_sensor_##offset); -sysfs_sensor(1) -sysfs_sensor(2) -sysfs_sensor(3) +sysfs_sensor(1); +sysfs_sensor(2); +sysfs_sensor(3); #define device_create_file_sensor(client, offset) \ do { \ @@ -1157,7 +1240,7 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) static void w83627hf_init_client(struct i2c_client *client) { struct w83627hf_data *data = i2c_get_clientdata(client); - int vid = 0, i; + int i; int type = data->type; u8 tmp; @@ -1191,10 +1274,15 @@ static void w83627hf_init_client(struct i2c_client *client) data->vid = w83627thf_read_gpio5(client) & 0x1f; } - /* Convert VID to voltage based on default VRM */ - data->vrm = DEFAULT_VRM; - if (type != w83697hf) - vid = vid_from_reg(vid, data->vrm); + /* Read VRM & OVT Config only once */ + if (w83627thf == data->type || w83637hf == data->type) { + data->vrm_ovt = + w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); + data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82; + } else { + /* Convert VID to voltage based on default VRM */ + data->vrm = DEFAULT_VRM; + } tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); for (i = 1; i <= 3; i++) { diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c index ac378b54b1cd..785203d39d68 100644 --- a/drivers/i2c/chips/w83781d.c +++ b/drivers/i2c/chips/w83781d.c @@ -320,7 +320,7 @@ show_regs_in_##offset (struct device *dev, char *buf) \ { \ return show_in(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL) +static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); #define sysfs_in_reg_offset(reg, offset) \ static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \ @@ -331,7 +331,7 @@ static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, { \ return store_in_##reg (dev, buf, count, 0x##offset); \ } \ -static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset) +static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset); #define sysfs_in_offsets(offset) \ sysfs_in_offset(offset); \ @@ -386,7 +386,7 @@ static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \ { \ return show_fan(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL) +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); #define sysfs_fan_min_offset(offset) \ static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \ @@ -397,7 +397,7 @@ static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, { \ return store_fan_min(dev, buf, count, 0x##offset); \ } \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset) +static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset); sysfs_fan_offset(1); sysfs_fan_min_offset(1); @@ -466,7 +466,7 @@ show_regs_temp_##offset (struct device *dev, char *buf) \ { \ return show_temp(dev, buf, 0x##offset); \ } \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL) +static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); #define sysfs_temp_reg_offset(reg, offset) \ static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \ @@ -477,7 +477,7 @@ static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *bu { \ return store_temp_##reg (dev, buf, count, 0x##offset); \ } \ -static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset) +static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); #define sysfs_temp_offsets(offset) \ sysfs_temp_offset(offset); \ @@ -503,7 +503,7 @@ show_vid_reg(struct device *dev, char *buf) } static -DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL) +DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ device_create_file(&client->dev, &dev_attr_in0_ref); static ssize_t @@ -527,7 +527,7 @@ store_vrm_reg(struct device *dev, const char *buf, size_t count) } static -DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg) +DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); #define device_create_file_vrm(client) \ device_create_file(&client->dev, &dev_attr_vrm); static ssize_t @@ -538,7 +538,7 @@ show_alarms_reg(struct device *dev, char *buf) } static -DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL) +DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); #define device_create_file_alarms(client) \ device_create_file(&client->dev, &dev_attr_alarms); static ssize_t show_beep_mask (struct device *dev, char *buf) @@ -598,7 +598,7 @@ static ssize_t store_regs_beep_##reg (struct device *dev, const char *buf, size_ { \ return store_beep_reg(dev, buf, count, BEEP_##REG); \ } \ -static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg) +static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg); sysfs_beep(ENABLE, enable); sysfs_beep(MASK, mask); @@ -665,7 +665,7 @@ static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, { \ return store_fan_div_reg(dev, buf, count, offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset) +static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset); sysfs_fan_div(1); sysfs_fan_div(2); @@ -744,7 +744,7 @@ static ssize_t store_regs_pwm_##offset (struct device *dev, const char *buf, siz { \ return store_pwm_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset) +static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset); #define sysfs_pwmenable(offset) \ static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \ @@ -755,7 +755,7 @@ static ssize_t store_regs_pwmenable_##offset (struct device *dev, const char *bu { \ return store_pwmenable_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset) +static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset); sysfs_pwm(1); sysfs_pwm(2); @@ -833,7 +833,7 @@ static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf, { \ return store_sensor_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset) +static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset); sysfs_sensor(1); sysfs_sensor(2); @@ -891,7 +891,7 @@ static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size { \ return store_rt_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset) +static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset); sysfs_rt(1); sysfs_rt(2); @@ -1491,7 +1491,7 @@ static void w83781d_init_client(struct i2c_client *client) { struct w83781d_data *data = i2c_get_clientdata(client); - int vid = 0, i, p; + int i, p; int type = data->type; u8 tmp; @@ -1513,14 +1513,7 @@ w83781d_init_client(struct i2c_client *client) w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); } - if (type != w83697hf) { - vid = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x0f; - vid |= - (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01) << - 4; - data->vrm = DEFAULT_VRM; - vid = vid_from_reg(vid, data->vrm); - } + data->vrm = 82; if ((type != w83781d) && (type != as99127f)) { tmp = w83781d_read_value(client, W83781D_REG_SCFG1); diff --git a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c index 52118f9bf11f..58575861fc78 100644 --- a/drivers/i2c/chips/w83l785ts.c +++ b/drivers/i2c/chips/w83l785ts.c @@ -137,8 +137,8 @@ static ssize_t show_temp_over(struct device *dev, char *buf) return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); } -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL) -static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL) +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); +static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL); /* * Real code diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index a0a4aa15aa97..4e5a3671d6e3 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -181,7 +181,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, struct i2c_smbus_ioctl_data data_arg; union i2c_smbus_data temp; struct i2c_msg *rdwr_pa; - u8 **data_ptrs; + u8 __user **data_ptrs; int i,datasize,res; unsigned long funcs; @@ -238,8 +238,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, return -EFAULT; } - data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *), - GFP_KERNEL); + data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); if (data_ptrs == NULL) { kfree(rdwr_pa); return -ENOMEM; @@ -252,7 +251,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, res = -EINVAL; break; } - data_ptrs[i] = rdwr_pa[i].buf; + data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); if(rdwr_pa[i].buf == NULL) { res = -ENOMEM; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index ec58f197f54f..8b1d16b9c1ad 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -95,6 +95,26 @@ if BLK_DEV_IDE comment "Please see Documentation/ide.txt for help/info on IDE drives" +config BLK_DEV_IDE_SATA + bool "Support for SATA (deprecated; conflicts with libata SATA driver)" + default n + ---help--- + There are two drivers for Serial ATA controllers. + + The main driver, "libata", exists inside the SCSI subsystem + and supports most modern SATA controllers. + + The IDE driver (which you are currently configuring) supports + a few first-generation SATA controllers. + + In order to eliminate conflicts between the two subsystems, + this config option enables the IDE driver's SATA support. + Normally this is disabled, as it is preferred that libata + supports SATA controllers, and this (IDE) driver supports + PATA controllers. + + If unsure, say N. + config BLK_DEV_HD_IDE bool "Use old disk-only driver on primary interface" depends on (X86 || SH_MPC1211) diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 05ea9a7057eb..5d35808ac781 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -660,7 +660,7 @@ static int hd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; - struct hd_geometry *loc = (struct hd_geometry *) arg; + struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; struct hd_geometry g; if (cmd != HDIO_GETGEO) diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index d6b052300dfa..30bdcb3ec22f 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -71,11 +71,7 @@ static struct amd_ide_chip { { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, 0x50, AMD_UDMA_133 }, { 0 } }; @@ -487,11 +483,7 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"), /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"), /* 13 */ DECLARE_NV_DEV("NFORCE-CK804"), - /* 14 */ DECLARE_NV_DEV("NFORCE-CK804-SATA"), - /* 15 */ DECLARE_NV_DEV("NFORCE-CK804-SATA2"), - /* 16 */ DECLARE_NV_DEV("NFORCE-MCP04"), - /* 17 */ DECLARE_NV_DEV("NFORCE-MCP04-SATA"), - /* 18 */ DECLARE_NV_DEV("NFORCE-MCP04-SATA2") + /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"), }; static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -512,17 +504,17 @@ static struct pci_device_id amd74xx_pci_tbl[] = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, +#endif { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, +#endif { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index e73279563a58..2150a18a8252 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -127,7 +127,9 @@ static struct pci_device_id generic_pci_tbl[] = { { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, +#endif { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index fec700bbacbc..26719f2c7932 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -793,9 +793,9 @@ static struct pci_device_id piix_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, -#ifndef CONFIG_SCSI_SATA +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, -#endif /* !CONFIG_SCSI_SATA */ +#endif { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_19, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20}, { 0, }, diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 5a7483ef6003..b1c9e8cd5d7c 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -21,6 +21,7 @@ * if neccessary */ +#include <linux/config.h> #include <linux/types.h> #include <linux/module.h> #include <linux/pci.h> @@ -1127,8 +1128,10 @@ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_devi static struct pci_device_id siimage_pci_tbl[] = { { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, +#endif { 0, }, }; MODULE_DEVICE_TABLE(pci, siimage_pci_tbl); diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index 10606f8f110e..4ee5d42e8a20 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -1095,7 +1095,7 @@ void stream_free(struct stream *s) /* File operations */ -static ssize_t amdtp_write(struct file *file, const char *buffer, size_t count, +static ssize_t amdtp_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset_is_ignored) { struct stream *s = file->private_data; @@ -1150,7 +1150,7 @@ static int amdtp_ioctl(struct inode *inode, struct file *file, { case AMDTP_IOC_PLUG: case AMDTP_IOC_CHANNEL: - if (copy_from_user(&cfg, (struct amdtp_ioctl *) arg, sizeof cfg)) + if (copy_from_user(&cfg, (struct amdtp_ioctl __user *) arg, sizeof cfg)) return -EFAULT; else return stream_configure(s, cmd, &cfg); diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 9964d6fbc5a1..626298dd3e99 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1333,7 +1333,7 @@ static int dv1394_fasync(int fd, struct file *file, int on) return 0; } -static ssize_t dv1394_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct video_card *video = file_to_video_card(file); DECLARE_WAITQUEUE(wait, current); @@ -1430,7 +1430,7 @@ static ssize_t dv1394_write(struct file *file, const char *buffer, size_t count, } -static ssize_t dv1394_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct video_card *video = file_to_video_card(file); DECLARE_WAITQUEUE(wait, current); @@ -1549,6 +1549,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, struct video_card *video = file_to_video_card(file); unsigned long flags; int ret = -EINVAL; + void __user *argp = (void __user *)arg; DECLARE_WAITQUEUE(wait, current); @@ -1718,10 +1719,10 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, case DV1394_IOC_INIT: { struct dv1394_init init; - if (arg == (unsigned long) NULL) { + if (!argp) { ret = do_dv1394_init_default(video); } else { - if (copy_from_user(&init, (void*)arg, sizeof(init))) { + if (copy_from_user(&init, argp, sizeof(init))) { ret = -EFAULT; goto out; } @@ -1767,7 +1768,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, spin_unlock_irqrestore(&video->spinlock, flags); - if (copy_to_user((void*)arg, &status, sizeof(status))) { + if (copy_to_user(argp, &status, sizeof(status))) { ret = -EFAULT; goto out; } diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h index 674d55c7f8eb..c93587be9cab 100644 --- a/drivers/ieee1394/raw1394-private.h +++ b/drivers/ieee1394/raw1394-private.h @@ -35,11 +35,11 @@ struct file_info { struct list_head addr_list; - u8 *fcp_buffer; + u8 __user *fcp_buffer; /* old ISO API */ u64 listen_channels; - quadlet_t *iso_buffer; + quadlet_t __user *iso_buffer; size_t iso_buffer_length; u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index dd43837d1d5f..35a9056aa30d 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -56,11 +56,11 @@ #include "raw1394-private.h" #if BITS_PER_LONG == 64 -#define int2ptr(x) ((void *)x) -#define ptr2int(x) ((u64)x) +#define int2ptr(x) ((void __user *)x) +#define ptr2int(x) ((u64)(unsigned long)(void __user *)x) #else -#define int2ptr(x) ((void *)(u32)x) -#define ptr2int(x) ((u64)(u32)x) +#define int2ptr(x) ((void __user *)(u32)x) +#define ptr2int(x) ((u64)(unsigned long)(void __user *)x) #endif #ifdef CONFIG_IEEE1394_VERBOSEDEBUG @@ -410,7 +410,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, } -static ssize_t raw1394_read(struct file *file, char *buffer, size_t count, +static ssize_t raw1394_read(struct file *file, char __user *buffer, size_t count, loff_t *offset_is_ignored) { struct file_info *fi = (struct file_info *)file->private_data; @@ -602,7 +602,7 @@ static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) if (fi->fcp_buffer) { req->req.error = RAW1394_ERROR_ALREADY; } else { - fi->fcp_buffer = (u8 *)int2ptr(req->req.recvb); + fi->fcp_buffer = int2ptr(req->req.recvb); } } else { if (!fi->fcp_buffer) { @@ -826,7 +826,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) return sizeof(struct raw1394_request); } - if (copy_from_user(packet->data, ((u8*) int2ptr(req->req.sendb)) + header_length, + if (copy_from_user(packet->data, int2ptr(req->req.sendb) + header_length, packet->data_size)) { req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; @@ -964,9 +964,8 @@ static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer, arm_req->buffer = NULL; arm_resp->buffer = NULL; if (rcode == RCODE_COMPLETE) { - arm_resp->buffer = ((byte_t *)(arm_resp) + - (sizeof(struct arm_response))); - memcpy (arm_resp->buffer, + byte_t *buf = (byte_t *)arm_resp + sizeof(struct arm_response); + memcpy (buf, (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), length); arm_resp->buffer = int2ptr((arm_addr->recvb) + @@ -1091,10 +1090,9 @@ static int arm_write (struct hpsb_host *host, int nodeid, int destid, (sizeof (struct arm_request_response))); arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + (sizeof(struct arm_request))); - arm_req->buffer = ((byte_t *)(arm_resp) + - (sizeof(struct arm_response))); arm_resp->buffer = NULL; - memcpy (arm_req->buffer, data, length); + memcpy ((byte_t *)arm_resp + sizeof(struct arm_response), + data, length); arm_req->buffer = int2ptr((arm_addr->recvb) + sizeof (struct arm_request_response) + sizeof (struct arm_request) + @@ -1233,6 +1231,7 @@ static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store, } } if (arm_addr->notification_options & ARM_LOCK) { + byte_t *buf1, *buf2; DBGMSG("arm_lock -> entering notification-section"); req = __alloc_pending_request(SLAB_ATOMIC); if (!req) { @@ -1258,26 +1257,22 @@ static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store, (sizeof (struct arm_request_response))); arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + (sizeof(struct arm_request))); - arm_req->buffer = ((byte_t *)(arm_resp) + - (sizeof(struct arm_response))); - arm_resp->buffer = ((byte_t *)(arm_req->buffer) + - (2* sizeof(*store))); + buf1 = (byte_t *)arm_resp + sizeof(struct arm_response); + buf2 = buf1 + 2 * sizeof(*store); if ((ext_tcode == EXTCODE_FETCH_ADD) || (ext_tcode == EXTCODE_LITTLE_ADD)) { arm_req->buffer_length = sizeof(*store); - memcpy (arm_req->buffer, &data, sizeof(*store)); + memcpy (buf1, &data, sizeof(*store)); } else { arm_req->buffer_length = 2 * sizeof(*store); - memcpy (arm_req->buffer, &arg, sizeof(*store)); - memcpy (((arm_req->buffer) + sizeof(*store)), - &data, sizeof(*store)); + memcpy (buf1, &arg, sizeof(*store)); + memcpy (buf1 + sizeof(*store), &data, sizeof(*store)); } if (rcode == RCODE_COMPLETE) { arm_resp->buffer_length = sizeof(*store); - memcpy (arm_resp->buffer, &old, sizeof(*store)); + memcpy (buf2, &old, sizeof(*store)); } else { - arm_resp->buffer = NULL; arm_resp->buffer_length = 0; } req->file_info = fi; @@ -1438,6 +1433,7 @@ static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, } } if (arm_addr->notification_options & ARM_LOCK) { + byte_t *buf1, *buf2; DBGMSG("arm_lock64 -> entering notification-section"); req = __alloc_pending_request(SLAB_ATOMIC); if (!req) { @@ -1463,26 +1459,22 @@ static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, (sizeof (struct arm_request_response))); arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + (sizeof(struct arm_request))); - arm_req->buffer = ((byte_t *)(arm_resp) + - (sizeof(struct arm_response))); - arm_resp->buffer = ((byte_t *)(arm_req->buffer) + - (2* sizeof(*store))); + buf1 = (byte_t *)arm_resp + sizeof(struct arm_response); + buf2 = buf1 + 2 * sizeof(*store); if ((ext_tcode == EXTCODE_FETCH_ADD) || (ext_tcode == EXTCODE_LITTLE_ADD)) { arm_req->buffer_length = sizeof(*store); - memcpy (arm_req->buffer, &data, sizeof(*store)); + memcpy (buf1, &data, sizeof(*store)); } else { arm_req->buffer_length = 2 * sizeof(*store); - memcpy (arm_req->buffer, &arg, sizeof(*store)); - memcpy (((arm_req->buffer) + sizeof(*store)), - &data, sizeof(*store)); + memcpy (buf1, &arg, sizeof(*store)); + memcpy (buf1 + sizeof(*store), &data, sizeof(*store)); } if (rcode == RCODE_COMPLETE) { arm_resp->buffer_length = sizeof(*store); - memcpy (arm_resp->buffer, &old, sizeof(*store)); + memcpy (buf2, &old, sizeof(*store)); } else { - arm_resp->buffer = NULL; arm_resp->buffer_length = 0; } req->file_info = fi; @@ -2146,7 +2138,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) } -static ssize_t raw1394_write(struct file *file, const char *buffer, size_t count, +static ssize_t raw1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset_is_ignored) { struct file_info *fi = (struct file_info *)file->private_data; @@ -2262,7 +2254,7 @@ static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_sta stat->xmit_cycle = iso->xmit_cycle; } -static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr) +static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr) { struct raw1394_iso_status stat; @@ -2294,7 +2286,7 @@ static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr) return 0; } -static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr) +static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr) { struct raw1394_iso_status stat; @@ -2322,7 +2314,7 @@ static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr) return 0; } -static int raw1394_iso_get_status(struct file_info *fi, void *uaddr) +static int raw1394_iso_get_status(struct file_info *fi, void __user *uaddr) { struct raw1394_iso_status stat; struct hpsb_iso *iso = fi->iso_handle; @@ -2338,7 +2330,7 @@ static int raw1394_iso_get_status(struct file_info *fi, void *uaddr) } /* copy N packet_infos out of the ringbuffer into user-supplied array */ -static int raw1394_iso_recv_packets(struct file_info *fi, void *uaddr) +static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr) { struct raw1394_iso_packets upackets; unsigned int packet = fi->iso_handle->first_packet; @@ -2369,7 +2361,7 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void *uaddr) } /* copy N packet_infos from user to ringbuffer, and queue them for transmission */ -static int raw1394_iso_send_packets(struct file_info *fi, void *uaddr) +static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr) { struct raw1394_iso_packets upackets; int i, rv; @@ -2426,14 +2418,15 @@ static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct file_info *fi = file->private_data; + void __user *argp = (void __user *)arg; switch(fi->iso_state) { case RAW1394_ISO_INACTIVE: switch(cmd) { case RAW1394_IOC_ISO_XMIT_INIT: - return raw1394_iso_xmit_init(fi, (void*) arg); + return raw1394_iso_xmit_init(fi, argp); case RAW1394_IOC_ISO_RECV_INIT: - return raw1394_iso_recv_init(fi, (void*) arg); + return raw1394_iso_recv_init(fi, argp); default: break; } @@ -2443,7 +2436,7 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm case RAW1394_IOC_ISO_RECV_START: { /* copy args from user-space */ int args[3]; - if (copy_from_user(&args[0], (void*) arg, sizeof(args))) + if (copy_from_user(&args[0], argp, sizeof(args))) return -EFAULT; return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); } @@ -2457,14 +2450,14 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: { /* copy the u64 from user-space */ u64 mask; - if (copy_from_user(&mask, (void*) arg, sizeof(mask))) + if (copy_from_user(&mask, argp, sizeof(mask))) return -EFAULT; return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask); } case RAW1394_IOC_ISO_GET_STATUS: - return raw1394_iso_get_status(fi, (void*) arg); + return raw1394_iso_get_status(fi, argp); case RAW1394_IOC_ISO_RECV_PACKETS: - return raw1394_iso_recv_packets(fi, (void*) arg); + return raw1394_iso_recv_packets(fi, argp); case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: return hpsb_iso_recv_release_packets(fi->iso_handle, arg); case RAW1394_IOC_ISO_RECV_FLUSH: @@ -2482,7 +2475,7 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm case RAW1394_IOC_ISO_XMIT_START: { /* copy two ints from user-space */ int args[2]; - if (copy_from_user(&args[0], (void*) arg, sizeof(args))) + if (copy_from_user(&args[0], argp, sizeof(args))) return -EFAULT; return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]); } @@ -2492,9 +2485,9 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm hpsb_iso_stop(fi->iso_handle); return 0; case RAW1394_IOC_ISO_GET_STATUS: - return raw1394_iso_get_status(fi, (void*) arg); + return raw1394_iso_get_status(fi, argp); case RAW1394_IOC_ISO_XMIT_PACKETS: - return raw1394_iso_send_packets(fi, (void*) arg); + return raw1394_iso_send_packets(fi, argp); case RAW1394_IOC_ISO_SHUTDOWN: raw1394_iso_shutdown(fi); return 0; diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h index 258ed558e496..35bfc38f013c 100644 --- a/drivers/ieee1394/raw1394.h +++ b/drivers/ieee1394/raw1394.h @@ -105,18 +105,18 @@ typedef struct arm_request { __u8 extended_transaction_code; __u32 generation; __u16 buffer_length; - __u8 *buffer; + __u8 __user *buffer; } *arm_request_t; typedef struct arm_response { __s32 response_code; __u16 buffer_length; - __u8 *buffer; + __u8 __user *buffer; } *arm_response_t; typedef struct arm_request_response { - struct arm_request *request; - struct arm_response *response; + struct arm_request __user *request; + struct arm_response __user *response; } *arm_request_response_t; /* rawiso API */ @@ -136,7 +136,7 @@ struct raw1394_iso_packet_info { /* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */ struct raw1394_iso_packets { __u32 n_packets; - struct raw1394_iso_packet_info *infos; + struct raw1394_iso_packet_info __user *infos; }; struct raw1394_iso_config { diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 7a757fc43f1d..e954d0834ff3 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -705,6 +705,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, struct file_ctx *ctx = (struct file_ctx *)file->private_data; struct ti_ohci *ohci = ctx->ohci; unsigned long flags; + void __user *argp = (void __user *)arg; switch(cmd) { @@ -716,7 +717,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, struct dma_iso_ctx *d; int i; - if (copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, argp, sizeof(v))) return -EFAULT; /* if channel < 0, find lowest available one */ @@ -813,7 +814,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, v.channel); } - if (copy_to_user((void *)arg, &v, sizeof(v))) + if (copy_to_user(argp, &v, sizeof(v))) return -EFAULT; return 0; @@ -825,7 +826,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, u64 mask; struct dma_iso_ctx *d; - if (copy_from_user(&channel, (void *)arg, sizeof(int))) + if (copy_from_user(&channel, argp, sizeof(int))) return -EFAULT; if (channel<0 || channel>(ISO_CHANNELS-1)) { @@ -860,7 +861,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, struct video1394_wait v; struct dma_iso_ctx *d; - if (copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, argp, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); @@ -923,7 +924,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, struct dma_iso_ctx *d; int i; - if (copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, argp, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); @@ -994,7 +995,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, spin_unlock_irqrestore(&d->lock, flags); v.buffer=i; - if (copy_to_user((void *)arg, &v, sizeof(v))) + if (copy_to_user(argp, &v, sizeof(v))) return -EFAULT; return 0; @@ -1007,7 +1008,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, qv.packet_sizes = NULL; - if (copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, argp, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); @@ -1023,7 +1024,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, unsigned int *psizes; int buf_size = d->nb_cmd * sizeof(unsigned int); - if (copy_from_user(&qv, (void *)arg, sizeof(qv))) + if (copy_from_user(&qv, argp, sizeof(qv))) return -EFAULT; psizes = kmalloc(buf_size, GFP_KERNEL); @@ -1111,7 +1112,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, struct video1394_wait v; struct dma_iso_ctx *d; - if (copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, argp, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 62ffcc67b050..a11be53573d0 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -320,8 +320,8 @@ isdn_ppp_open(int min, struct file *file) is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ #endif #ifdef CONFIG_IPPP_FILTER - is->pass_filter.filter = NULL; - is->active_filter.filter = NULL; + is->pass_filter = NULL; + is->active_filter = NULL; #endif is->state = IPPP_OPEN; @@ -378,13 +378,13 @@ isdn_ppp_release(int min, struct file *file) is->slcomp = NULL; #endif #ifdef CONFIG_IPPP_FILTER - if (is->pass_filter.filter) { - kfree(is->pass_filter.filter); - is->pass_filter.filter = NULL; + if (is->pass_filter) { + kfree(is->pass_filter); + is->pass_filter = NULL; } - if (is->active_filter.filter) { - kfree(is->active_filter.filter); - is->active_filter.filter = NULL; + if (is->active_filter) { + kfree(is->active_filter); + is->active_filter = NULL; } #endif @@ -414,11 +414,11 @@ isdn_ppp_release(int min, struct file *file) * get_arg .. ioctl helper */ static int -get_arg(void *b, void *val, int len) +get_arg(void __user *b, void *val, int len) { if (len <= 0) len = sizeof(void *); - if (copy_from_user((void *) val, b, len)) + if (copy_from_user(val, b, len)) return -EFAULT; return 0; } @@ -427,15 +427,50 @@ get_arg(void *b, void *val, int len) * set arg .. ioctl helper */ static int -set_arg(void *b, void *val,int len) +set_arg(void __user *b, void *val,int len) { if(len <= 0) len = sizeof(void *); - if (copy_to_user(b, (void *) val, len)) + if (copy_to_user(b, val, len)) return -EFAULT; return 0; } +static int get_filter(void __user *arg, struct sock_filter **p) +{ + struct sock_fprog uprog; + struct sock_filter *code = NULL; + int len, err; + + if (copy_from_user(&uprog, arg, sizeof(uprog))) + return -EFAULT; + + if (!uprog.len) { + *p = NULL; + return 0; + } + + /* uprog.len is unsigned short, so no overflow here */ + len = uprog.len * sizeof(struct sock_filter); + code = kmalloc(len, GFP_KERNEL); + if (code == NULL) + return -ENOMEM; + + if (copy_from_user(code, uprog.filter, len)) { + kfree(code); + return -EFAULT; + } + + err = sk_chk_filter(code, uprog.len); + if (err) { + kfree(code); + return err; + } + + *p = code; + return uprog.len; +} + /* * ippp device ioctl */ @@ -447,6 +482,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) struct ippp_struct *is; isdn_net_local *lp; struct isdn_ppp_comp_data data; + void __user *argp = (void __user *)arg; is = (struct ippp_struct *) file->private_data; lp = is->lp; @@ -462,7 +498,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_ISDN_MPP if (!(is->state & IPPP_CONNECT)) return -EINVAL; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + if ((r = get_arg(argp, &val, sizeof(val) ))) return r; printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n", (int) min, (int) is->unit, (int) val); @@ -472,30 +508,30 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) #endif break; case PPPIOCGUNIT: /* get ppp/isdn unit number */ - if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) ))) + if ((r = set_arg(argp, &is->unit, sizeof(is->unit) ))) return r; break; case PPPIOCGIFNAME: if(!lp) return -EINVAL; - if ((r = set_arg((void *) arg, lp->name, strlen(lp->name)))) + if ((r = set_arg(argp, lp->name, strlen(lp->name)))) return r; break; case PPPIOCGMPFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) ))) + if ((r = set_arg(argp, &is->mpppcfg, sizeof(is->mpppcfg) ))) return r; break; case PPPIOCSMPFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + if ((r = get_arg(argp, &val, sizeof(val) ))) return r; is->mpppcfg = val; break; case PPPIOCGFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) ))) + if ((r = set_arg(argp, &is->pppcfg,sizeof(is->pppcfg) ))) return r; break; case PPPIOCSFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) { + if ((r = get_arg(argp, &val, sizeof(val) ))) { return r; } if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) { @@ -512,12 +548,12 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) if (lp) { struct ppp_idle pidle; pidle.xmit_idle = pidle.recv_idle = lp->huptimer; - if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle)))) + if ((r = set_arg(argp, &pidle,sizeof(struct ppp_idle)))) return r; } break; case PPPIOCSMRU: /* set receive unit size for PPP */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + if ((r = get_arg(argp, &val, sizeof(val) ))) return r; is->mru = val; break; @@ -526,7 +562,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) case PPPIOCSMPMTU: break; case PPPIOCSMAXCID: /* set the maximum compression slot id */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + if ((r = get_arg(argp, &val, sizeof(val) ))) return r; val++; if (is->maxcid != val) { @@ -549,11 +585,11 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) } break; case PPPIOCGDEBUG: - if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) ))) + if ((r = set_arg(argp, &is->debug, sizeof(is->debug) ))) return r; break; case PPPIOCSDEBUG: - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + if ((r = get_arg(argp, &val, sizeof(val) ))) return r; is->debug = val; break; @@ -568,12 +604,12 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) protos[j] |= (0x1<<i); ipc = ipc->next; } - if ((r = set_arg((void *) arg,protos,8*sizeof(long) ))) + if ((r = set_arg(argp,protos,8*sizeof(long) ))) return r; } break; case PPPIOCSCOMPRESSOR: - if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data)))) + if ((r = get_arg(argp, &data, sizeof(struct isdn_ppp_comp_data)))) return r; return isdn_ppp_set_compressor(is, &data); case PPPIOCGCALLINFO: @@ -594,38 +630,29 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) if(lp->flags & ISDN_NET_CALLBACK) pci.calltype |= CALLTYPE_CALLBACK; } - return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo)); + return set_arg(argp,&pci,sizeof(struct pppcallinfo)); } #ifdef CONFIG_IPPP_FILTER case PPPIOCSPASS: + { + struct sock_filter *code; + int len = get_filter(argp, &code); + if (len < 0) + return len; + kfree(is->pass_filter); + is->pass_filter = code; + is->pass_len = len; + break; + } case PPPIOCSACTIVE: { - struct sock_fprog uprog, *filtp; - struct sock_filter *code = NULL; - int len, err; - - if (copy_from_user(&uprog, (void *) arg, sizeof(uprog))) - return -EFAULT; - if (uprog.len > 0) { - len = uprog.len * sizeof(struct sock_filter); - code = kmalloc(len, GFP_KERNEL); - if (code == NULL) - return -ENOMEM; - if (copy_from_user(code, uprog.filter, len)) { - kfree(code); - return -EFAULT; - } - err = sk_chk_filter(code, uprog.len); - if (err) { - kfree(code); - return err; - } - } - filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter; - if (filtp->filter) - kfree(filtp->filter); - filtp->filter = code; - filtp->len = uprog.len; + struct sock_filter *code; + int len = get_filter(argp, &code); + if (len < 0) + return len; + kfree(is->active_filter); + is->active_filter = code; + is->active_len = len; break; } #endif /* CONFIG_IPPP_FILTER */ @@ -733,7 +760,7 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) */ int -isdn_ppp_read(int min, struct file *file, char *buf, int count) +isdn_ppp_read(int min, struct file *file, char __user *buf, int count) { struct ippp_struct *is; struct ippp_buf_queue *b; @@ -746,7 +773,7 @@ isdn_ppp_read(int min, struct file *file, char *buf, int count) if (!(is->state & IPPP_OPEN)) return 0; - if ((r = verify_area(VERIFY_WRITE, (void *) buf, count))) + if ((r = verify_area(VERIFY_WRITE, buf, count))) return r; spin_lock_irqsave(&is->buflock, flags); @@ -773,7 +800,7 @@ isdn_ppp_read(int min, struct file *file, char *buf, int count) */ int -isdn_ppp_write(int min, struct file *file, const char *buf, int count) +isdn_ppp_write(int min, struct file *file, const char __user *buf, int count) { isdn_net_local *lp; struct ippp_struct *is; @@ -1128,17 +1155,16 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *p = 0; /* indicate inbound in DLT_LINUX_SLL */ } - if (is->pass_filter.filter - && sk_run_filter(skb, is->pass_filter.filter, - is->pass_filter.len) == 0) { + if (is->pass_filter + && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0) { if (is->debug & 0x2) printk(KERN_DEBUG "IPPP: inbound frame filtered.\n"); kfree_skb(skb); return; } - if (!(is->active_filter.filter - && sk_run_filter(skb, is->active_filter.filter, - is->active_filter.len) == 0)) { + if (!(is->active_filter + && sk_run_filter(skb, is->active_filter, + is->active_len) == 0)) { if (is->debug & 0x2) printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n"); lp->huptimer = 0; @@ -1276,17 +1302,16 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) *p = htons(proto); } - if (ipt->pass_filter.filter - && sk_run_filter(skb, ipt->pass_filter.filter, - ipt->pass_filter.len) == 0) { + if (ipt->pass_filter + && sk_run_filter(skb, ipt->pass_filter, ipt->pass_len) == 0) { if (ipt->debug & 0x4) printk(KERN_DEBUG "IPPP: outbound frame filtered.\n"); kfree_skb(skb); goto unlock; } - if (!(ipt->active_filter.filter - && sk_run_filter(skb, ipt->active_filter.filter, - ipt->active_filter.len) == 0)) { + if (!(ipt->active_filter + && sk_run_filter(skb, ipt->active_filter, + ipt->active_len) == 0)) { if (ipt->debug & 0x4) printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n"); lp->huptimer = 0; @@ -1475,12 +1500,10 @@ int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp) *p = htons(proto); } - drop |= is->pass_filter.filter - && sk_run_filter(skb, is->pass_filter.filter, - is->pass_filter.len) == 0; - drop |= is->active_filter.filter - && sk_run_filter(skb, is->active_filter.filter, - is->active_filter.len) == 0; + drop |= is->pass_filter + && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0; + drop |= is->active_filter + && sk_run_filter(skb, is->active_filter, is->active_len) == 0; skb_push(skb, IPPP_MAX_HEADER - 4); return drop; @@ -1969,12 +1992,11 @@ out: static int isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev) { - struct ppp_stats *res, - t; + struct ppp_stats __user *res = ifr->ifr_data; + struct ppp_stats t; isdn_net_local *lp = (isdn_net_local *) dev->priv; int err; - res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats)); if (err) @@ -2004,7 +2026,8 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev) } #endif } - if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT; + if (copy_to_user(res, &t, sizeof(struct ppp_stats))) + return -EFAULT; return 0; } @@ -2012,7 +2035,6 @@ int isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int error=0; - char *r; int len; isdn_net_local *lp = (isdn_net_local *) dev->priv; @@ -2023,9 +2045,8 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) switch (cmd) { #define PPP_VERSION "2.3.7" case SIOCGPPPVER: - r = (char *) ifr->ifr_ifru.ifru_data; len = strlen(PPP_VERSION) + 1; - if (copy_to_user(r, PPP_VERSION, len)) + if (copy_to_user(ifr->ifr_data, PPP_VERSION, len)) error = -EFAULT; break; diff --git a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h index f14b8a849a9d..8cc05c7ccf78 100644 --- a/drivers/isdn/i4l/isdn_ppp.h +++ b/drivers/isdn/i4l/isdn_ppp.h @@ -12,8 +12,8 @@ #include <linux/ppp_defs.h> /* for PPP_PROTOCOL */ #include <linux/isdn_ppp.h> /* for isdn_ppp info */ -extern int isdn_ppp_read(int, struct file *, char *, int); -extern int isdn_ppp_write(int, struct file *, const char *, int); +extern int isdn_ppp_read(int, struct file *, char __user *, int); +extern int isdn_ppp_write(int, struct file *, const char __user *, int); extern int isdn_ppp_open(int, struct file *); extern int isdn_ppp_init(void); extern void isdn_ppp_cleanup(void); diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 53dc879651e4..8ffa894c3017 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -55,8 +55,9 @@ #include <linux/if_arp.h> /* For ARPHRD_ETHER */ #include <linux/ip.h> #include <linux/tcp.h> +#include <linux/percpu.h> -static struct net_device_stats *loopback_stats; +static DEFINE_PER_CPU(struct net_device_stats, loopback_stats); #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) @@ -124,6 +125,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) */ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) { + struct net_device_stats *lb_stats; skb_orphan(skb); @@ -142,13 +144,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) } dev->last_rx = jiffies; - if (likely(loopback_stats)) { - get_cpu_ptr(loopback_stats)->rx_bytes += skb->len; - get_cpu_ptr(loopback_stats)->tx_bytes += skb->len; - get_cpu_ptr(loopback_stats)->rx_packets++; - get_cpu_ptr(loopback_stats)->tx_packets++; - put_cpu_ptr(loopback_stats); - } + + lb_stats = &per_cpu(loopback_stats, get_cpu()); + lb_stats->rx_bytes += skb->len; + lb_stats->tx_bytes += skb->len; + lb_stats->rx_packets++; + lb_stats->tx_packets++; + put_cpu(); netif_rx(skb); @@ -165,17 +167,17 @@ static struct net_device_stats *get_stats(struct net_device *dev) } memset(stats, 0, sizeof(struct net_device_stats)); - if (!loopback_stats) { - return stats; - } for (i=0; i < NR_CPUS; i++) { + struct net_device_stats *lb_stats; + if (!cpu_possible(i)) continue; - stats->rx_bytes += per_cpu_ptr(loopback_stats, i)->rx_bytes; - stats->tx_bytes += per_cpu_ptr(loopback_stats, i)->tx_bytes; - stats->rx_packets += per_cpu_ptr(loopback_stats, i)->rx_packets; - stats->tx_packets += per_cpu_ptr(loopback_stats, i)->tx_packets; + lb_stats = &per_cpu(loopback_stats, i); + stats->rx_bytes += lb_stats->rx_bytes; + stats->tx_bytes += lb_stats->tx_bytes; + stats->rx_packets += lb_stats->rx_packets; + stats->tx_packets += lb_stats->tx_packets; } return stats; @@ -211,8 +213,6 @@ int __init loopback_init(void) loopback_dev.priv = stats; loopback_dev.get_stats = &get_stats; } - - loopback_stats = alloc_percpu(struct net_device_stats); return register_netdev(&loopback_dev); }; diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index ffd5ac3a848e..8523970c73ed 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -129,8 +129,9 @@ struct ppp { #endif /* CONFIG_PPP_MULTILINK */ struct net_device_stats stats; /* statistics */ #ifdef CONFIG_PPP_FILTER - struct sock_fprog pass_filter; /* filter for packets to pass */ - struct sock_fprog active_filter;/* filter for pkts to reset idle */ + struct sock_filter *pass_filter; /* filter for packets to pass */ + struct sock_filter *active_filter;/* filter for pkts to reset idle */ + unsigned pass_len, active_len; #endif /* CONFIG_PPP_FILTER */ }; @@ -493,6 +494,43 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait) return mask; } +static int get_filter(void __user *arg, struct sock_filter **p) +{ + struct sock_fprog uprog; + struct sock_filter *code = NULL; + int len, err; + + if (copy_from_user(&uprog, arg, sizeof(uprog))) + return -EFAULT; + + if (uprog.len > BPF_MAXINSNS) + return -EINVAL; + + if (!uprog.len) { + *p = NULL; + return 0; + } + + len = uprog.len * sizeof(struct sock_filter); + code = kmalloc(len, GFP_KERNEL); + if (code == NULL) + return -ENOMEM; + + if (copy_from_user(code, uprog.filter, len)) { + kfree(code); + return -EFAULT; + } + + err = sk_chk_filter(code, uprog.len); + if (err) { + kfree(code); + return err; + } + + *p = code; + return uprog.len; +} + static int ppp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -503,6 +541,8 @@ static int ppp_ioctl(struct inode *inode, struct file *file, struct npioctl npi; int unit, cflags; struct slcompress *vj; + void __user *argp = (void __user *)arg; + int __user *p = argp; if (pf == 0) return ppp_unattached_ioctl(pf, file, cmd, arg); @@ -540,7 +580,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, switch (cmd) { case PPPIOCCONNECT: - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; err = ppp_connect_channel(pch, unit); break; @@ -569,14 +609,14 @@ static int ppp_ioctl(struct inode *inode, struct file *file, ppp = PF_TO_PPP(pf); switch (cmd) { case PPPIOCSMRU: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp->mru = val; err = 0; break; case PPPIOCSFLAGS: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp_lock(ppp); cflags = ppp->flags & ~val; @@ -589,7 +629,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, case PPPIOCGFLAGS: val = ppp->flags | ppp->xstate | ppp->rstate; - if (put_user(val, (int *) arg)) + if (put_user(val, p)) break; err = 0; break; @@ -599,20 +639,20 @@ static int ppp_ioctl(struct inode *inode, struct file *file, break; case PPPIOCGUNIT: - if (put_user(ppp->file.index, (int *) arg)) + if (put_user(ppp->file.index, p)) break; err = 0; break; case PPPIOCSDEBUG: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp->debug = val; err = 0; break; case PPPIOCGDEBUG: - if (put_user(ppp->debug, (int *) arg)) + if (put_user(ppp->debug, p)) break; err = 0; break; @@ -620,13 +660,13 @@ static int ppp_ioctl(struct inode *inode, struct file *file, case PPPIOCGIDLE: idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ; idle.recv_idle = (jiffies - ppp->last_recv) / HZ; - if (copy_to_user((void __user *) arg, &idle, sizeof(idle))) + if (copy_to_user(argp, &idle, sizeof(idle))) break; err = 0; break; case PPPIOCSMAXCID: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; val2 = 15; if ((val >> 16) != 0) { @@ -649,7 +689,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, case PPPIOCGNPMODE: case PPPIOCSNPMODE: - if (copy_from_user(&npi, (void __user *) arg, sizeof(npi))) + if (copy_from_user(&npi, argp, sizeof(npi))) break; err = proto_to_npindex(npi.protocol); if (err < 0) @@ -658,7 +698,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, if (cmd == PPPIOCGNPMODE) { err = -EFAULT; npi.mode = ppp->npmode[i]; - if (copy_to_user((void __user *) arg, &npi, sizeof(npi))) + if (copy_to_user(argp, &npi, sizeof(npi))) break; } else { ppp->npmode[i] = npi.mode; @@ -670,49 +710,38 @@ static int ppp_ioctl(struct inode *inode, struct file *file, #ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: + { + struct sock_filter *code; + err = get_filter(argp, &code); + if (err >= 0) { + ppp_lock(ppp); + kfree(ppp->pass_filter); + ppp->pass_filter = code; + ppp->pass_len = err; + ppp_unlock(ppp); + err = 0; + } + break; + } case PPPIOCSACTIVE: { - struct sock_fprog uprog, *filtp; - struct sock_filter *code = NULL; - int len; - - if (copy_from_user(&uprog, (void __user *) arg, sizeof(uprog))) - break; - err = -EINVAL; - if (uprog.len > BPF_MAXINSNS) - break; - err = -ENOMEM; - if (uprog.len > 0) { - len = uprog.len * sizeof(struct sock_filter); - code = kmalloc(len, GFP_KERNEL); - if (code == NULL) - break; - err = -EFAULT; - if (copy_from_user(code, (void __user *) uprog.filter, len)) { - kfree(code); - break; - } - err = sk_chk_filter(code, uprog.len); - if (err) { - kfree(code); - break; - } + struct sock_filter *code; + err = get_filter(argp, &code); + if (err >= 0) { + ppp_lock(ppp); + kfree(ppp->active_filter); + ppp->active_filter = code; + ppp->active_len = err; + ppp_unlock(ppp); + err = 0; } - filtp = (cmd == PPPIOCSPASS)? &ppp->pass_filter: &ppp->active_filter; - ppp_lock(ppp); - if (filtp->filter) - kfree(filtp->filter); - filtp->filter = code; - filtp->len = uprog.len; - ppp_unlock(ppp); - err = 0; break; } #endif /* CONFIG_PPP_FILTER */ #ifdef CONFIG_PPP_MULTILINK case PPPIOCSMRRU: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp_recv_lock(ppp); ppp->mrru = val; @@ -734,11 +763,12 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, int unit, err = -EFAULT; struct ppp *ppp; struct channel *chan; + int __user *p = (int __user *)arg; switch (cmd) { case PPPIOCNEWUNIT: /* Create a new ppp unit */ - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; ppp = ppp_create_interface(unit, &err); if (ppp == 0) @@ -746,14 +776,14 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, file->private_data = &ppp->file; ppp->owner = file; err = -EFAULT; - if (put_user(ppp->file.index, (int *) arg)) + if (put_user(ppp->file.index, p)) break; err = 0; break; case PPPIOCATTACH: /* Attach to an existing ppp unit */ - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; down(&all_ppp_sem); err = -ENXIO; @@ -767,7 +797,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, break; case PPPIOCATTCHAN: - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; spin_lock_bh(&all_channels_lock); err = -ENXIO; @@ -999,18 +1029,18 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) *p = htons(4); /* indicate outbound in DLT_LINUX_SLL */; } - if (ppp->pass_filter.filter - && sk_run_filter(skb, ppp->pass_filter.filter, - ppp->pass_filter.len) == 0) { + if (ppp->pass_filter + && sk_run_filter(skb, ppp->pass_filter, + ppp->pass_len) == 0) { if (ppp->debug & 1) printk(KERN_DEBUG "PPP: outbound frame not passed\n"); kfree_skb(skb); return; } /* if this packet passes the active filter, record the time */ - if (!(ppp->active_filter.filter - && sk_run_filter(skb, ppp->active_filter.filter, - ppp->active_filter.len) == 0)) + if (!(ppp->active_filter + && sk_run_filter(skb, ppp->active_filter, + ppp->active_len) == 0)) ppp->last_xmit = jiffies; skb_pull(skb, 2); #else @@ -1546,17 +1576,17 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) *p = 0; /* indicate inbound in DLT_LINUX_SLL */ } - if (ppp->pass_filter.filter - && sk_run_filter(skb, ppp->pass_filter.filter, - ppp->pass_filter.len) == 0) { + if (ppp->pass_filter + && sk_run_filter(skb, ppp->pass_filter, + ppp->pass_len) == 0) { if (ppp->debug & 1) printk(KERN_DEBUG "PPP: inbound frame not passed\n"); kfree_skb(skb); return; } - if (!(ppp->active_filter.filter - && sk_run_filter(skb, ppp->active_filter.filter, - ppp->active_filter.len) == 0)) + if (!(ppp->active_filter + && sk_run_filter(skb, ppp->active_filter, + ppp->active_len) == 0)) ppp->last_recv = jiffies; skb_pull(skb, 2); #else @@ -2423,13 +2453,13 @@ static void ppp_destroy_interface(struct ppp *ppp) skb_queue_purge(&ppp->mrq); #endif /* CONFIG_PPP_MULTILINK */ #ifdef CONFIG_PPP_FILTER - if (ppp->pass_filter.filter) { - kfree(ppp->pass_filter.filter); - ppp->pass_filter.filter = NULL; + if (ppp->pass_filter) { + kfree(ppp->pass_filter); + ppp->pass_filter = NULL; } - if (ppp->active_filter.filter) { - kfree(ppp->active_filter.filter); - ppp->active_filter.filter = 0; + if (ppp->active_filter) { + kfree(ppp->active_filter); + ppp->active_filter = 0; } #endif /* CONFIG_PPP_FILTER */ diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index b831eef1bca2..6fe6f3601a98 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -33,6 +33,7 @@ #include <linux/crc32.h> #include <linux/random.h> #include <linux/workqueue.h> +#include <linux/if_vlan.h> #include <asm/system.h> #include <asm/bitops.h> @@ -742,7 +743,7 @@ static void gem_rx(struct gem *gp) PCI_DMA_FROMDEVICE); gp->rx_skbs[entry] = new_skb; new_skb->dev = gp->dev; - skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET)); + skb_put(new_skb, (gp->rx_buf_sz + RX_OFFSET)); rxd->buffer = cpu_to_le64(pci_map_page(gp->pdev, virt_to_page(new_skb->data), offset_in_page(new_skb->data), @@ -1482,6 +1483,9 @@ static void gem_init_rings(struct gem *gp) gem_clean_rings(gp); + gp->rx_buf_sz = max(dev->mtu + ETH_HLEN + VLAN_HLEN, + (unsigned)VLAN_ETH_FRAME_LEN); + for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; struct gem_rxd *rxd = &gb->rxd[i]; @@ -1495,7 +1499,7 @@ static void gem_init_rings(struct gem *gp) gp->rx_skbs[i] = skb; skb->dev = dev; - skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET)); + skb_put(skb, (gp->rx_buf_sz + RX_OFFSET)); dma_addr = pci_map_page(gp->pdev, virt_to_page(skb->data), offset_in_page(skb->data), @@ -1750,7 +1754,7 @@ static void gem_init_mac(struct gem *gp) writel(0x40, gp->regs + MAC_MINFSZ); /* Ethernet payload + header + FCS + optional VLAN tag. */ - writel(0x20000000 | (gp->dev->mtu + ETH_HLEN + 4 + 4), gp->regs + MAC_MAXFSZ); + writel(0x20000000 | (gp->rx_buf_sz + 4), gp->regs + MAC_MAXFSZ); writel(0x07, gp->regs + MAC_PASIZE); writel(0x04, gp->regs + MAC_JAMSIZE); @@ -1827,7 +1831,7 @@ static void gem_init_pause_thresholds(struct gem *gp) if (gp->rx_fifo_sz <= (2 * 1024)) { gp->rx_pause_off = gp->rx_pause_on = gp->rx_fifo_sz; } else { - int max_frame = (gp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63; + int max_frame = (gp->rx_buf_sz + 4 + 64) & ~63; int off = (gp->rx_fifo_sz - (max_frame * 2)); int on = off - max_frame; diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h index ab83530f20ae..eed77bfe1b60 100644 --- a/drivers/net/sungem.h +++ b/drivers/net/sungem.h @@ -911,7 +911,7 @@ struct gem_rxd { (GP)->tx_old - (GP)->tx_new - 1) #define RX_OFFSET 2 -#define RX_BUF_ALLOC_SIZE(gp) ((gp)->dev->mtu + 46 + RX_OFFSET + 64) +#define RX_BUF_ALLOC_SIZE(gp) ((gp)->rx_buf_sz + 28 + RX_OFFSET + 64) #define RX_COPY_THRESHOLD 256 @@ -979,6 +979,7 @@ struct gem { int rx_fifo_sz; int rx_pause_off; int rx_pause_on; + int rx_buf_sz; int mii_phy_addr; u32 mac_rx_cfg; diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 10fa8e79d98e..dd1c6155fdd3 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -127,6 +127,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */ #include <linux/ioport.h> #include <linux/netdevice.h> +#include <linux/ip.h> #include <linux/trdevice.h> #include <linux/ibmtr.h> diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index 7f471804045e..e8cfa4fc993a 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -220,7 +220,8 @@ static int c101_close(struct net_device *dev) static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync; + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index a4d0452c3c97..da86c5132a4d 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -301,9 +301,9 @@ static char *chrdev_setup_rx(struct channel_data *channel, int size); static int chrdev_rx_done(struct channel_data *channel); static int chrdev_tx_done(struct channel_data *channel, int size); static ssize_t cosa_read(struct file *file, - char *buf, size_t count, loff_t *ppos); + char __user *buf, size_t count, loff_t *ppos); static ssize_t cosa_write(struct file *file, - const char *buf, size_t count, loff_t *ppos); + const char __user *buf, size_t count, loff_t *ppos); static unsigned int cosa_poll(struct file *file, poll_table *poll); static int cosa_open(struct inode *inode, struct file *file); static int cosa_release(struct inode *inode, struct file *file); @@ -330,13 +330,13 @@ static struct file_operations cosa_fops = { /* Ioctls */ static int cosa_start(struct cosa_data *cosa, int address); static int cosa_reset(struct cosa_data *cosa); -static int cosa_download(struct cosa_data *cosa, unsigned long a); -static int cosa_readmem(struct cosa_data *cosa, unsigned long a); +static int cosa_download(struct cosa_data *cosa, void __user *a); +static int cosa_readmem(struct cosa_data *cosa, void __user *a); /* COSA/SRP ROM monitor */ -static int download(struct cosa_data *cosa, const char *data, int addr, int len); +static int download(struct cosa_data *cosa, const char __user *data, int addr, int len); static int startmicrocode(struct cosa_data *cosa, int address); -static int readmem(struct cosa_data *cosa, char *data, int addr, int len); +static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len); static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id); /* Auxilliary functions */ @@ -830,7 +830,7 @@ static void chardev_channel_init(struct channel_data *chan) } static ssize_t cosa_read(struct file *file, - char *buf, size_t count, loff_t *ppos) + char __user *buf, size_t count, loff_t *ppos) { DECLARE_WAITQUEUE(wait, current); unsigned long flags; @@ -905,7 +905,7 @@ static int chrdev_rx_done(struct channel_data *chan) static ssize_t cosa_write(struct file *file, - const char *buf, size_t count, loff_t *ppos) + const char __user *buf, size_t count, loff_t *ppos) { DECLARE_WAITQUEUE(wait, current); struct channel_data *chan = file->private_data; @@ -1066,7 +1066,7 @@ static inline int cosa_reset(struct cosa_data *cosa) } /* High-level function to download data into COSA memory. Calls download() */ -static inline int cosa_download(struct cosa_data *cosa, unsigned long arg) +static inline int cosa_download(struct cosa_data *cosa, void __user *arg) { struct cosa_download d; int i; @@ -1080,7 +1080,7 @@ static inline int cosa_download(struct cosa_data *cosa, unsigned long arg) return -EPERM; } - if (copy_from_user(&d, (void __user *) arg, sizeof(d))) + if (copy_from_user(&d, arg, sizeof(d))) return -EFAULT; if (d.addr < 0 || d.addr > COSA_MAX_FIRMWARE_SIZE) @@ -1105,7 +1105,7 @@ static inline int cosa_download(struct cosa_data *cosa, unsigned long arg) } /* High-level function to read COSA memory. Calls readmem() */ -static inline int cosa_readmem(struct cosa_data *cosa, unsigned long arg) +static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg) { struct cosa_download d; int i; @@ -1120,7 +1120,7 @@ static inline int cosa_readmem(struct cosa_data *cosa, unsigned long arg) return -EPERM; } - if (copy_from_user(&d, (void __user *) arg, sizeof(d))) + if (copy_from_user(&d, arg, sizeof(d))) return -EFAULT; /* If something fails, force the user to reset the card */ @@ -1167,7 +1167,7 @@ static inline int cosa_start(struct cosa_data *cosa, int address) } /* Buffer of size at least COSA_MAX_ID_STRING is expected */ -static inline int cosa_getidstr(struct cosa_data *cosa, char *string) +static inline int cosa_getidstr(struct cosa_data *cosa, char __user *string) { int l = strlen(cosa->id_string)+1; if (copy_to_user(string, cosa->id_string, l)) @@ -1176,7 +1176,7 @@ static inline int cosa_getidstr(struct cosa_data *cosa, char *string) } /* Buffer of size at least COSA_MAX_ID_STRING is expected */ -static inline int cosa_gettype(struct cosa_data *cosa, char *string) +static inline int cosa_gettype(struct cosa_data *cosa, char __user *string) { int l = strlen(cosa->type)+1; if (copy_to_user(string, cosa->type, l)) @@ -1187,6 +1187,7 @@ static inline int cosa_gettype(struct cosa_data *cosa, char *string) static int cosa_ioctl_common(struct cosa_data *cosa, struct channel_data *channel, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; switch(cmd) { case COSAIORSET: /* Reset the device */ if (!capable(CAP_NET_ADMIN)) @@ -1200,15 +1201,15 @@ static int cosa_ioctl_common(struct cosa_data *cosa, if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return cosa_download(cosa, arg); + return cosa_download(cosa, argp); case COSAIORMEM: if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return cosa_readmem(cosa, arg); + return cosa_readmem(cosa, argp); case COSAIORTYPE: - return cosa_gettype(cosa, (char *)arg); + return cosa_gettype(cosa, argp); case COSAIORIDSTR: - return cosa_getidstr(cosa, (char *)arg); + return cosa_getidstr(cosa, argp); case COSAIONRCARDS: return nr_cards; case COSAIONRCHANS: @@ -1434,7 +1435,7 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len) * by a single space. Monitor has to reply with a space. Now the download * begins. After the download monitor replies with "\r\n." (CR LF dot). */ -static int download(struct cosa_data *cosa, const char *microcode, int length, int address) +static int download(struct cosa_data *cosa, const char __user *microcode, int length, int address) { int i; @@ -1508,7 +1509,7 @@ static int startmicrocode(struct cosa_data *cosa, int address) * This routine is not needed during the normal operation and serves * for debugging purposes only. */ -static int readmem(struct cosa_data *cosa, char *microcode, int length, int address) +static int readmem(struct cosa_data *cosa, char __user *microcode, int length, int address) { if (put_wait_data(cosa, 'r') == -1) return -1; if ((get_wait_data(cosa)) != 'r') return -2; diff --git a/drivers/net/wan/cosa.h b/drivers/net/wan/cosa.h index b59e3efffa73..63a8a5c42f0a 100644 --- a/drivers/net/wan/cosa.h +++ b/drivers/net/wan/cosa.h @@ -66,7 +66,7 @@ /* ioctls */ struct cosa_download { int addr, len; - char *code; + char __user *code; }; /* Reset the device */ diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index b98f27e99a9a..4cbda752b07e 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -1296,7 +1296,7 @@ done: static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - sync_serial_settings *line = ifr->ifr_settings.ifs_ifsu.sync; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; struct dscc4_dev_priv *dpriv = dscc4_priv(dev); const size_t size = sizeof(dpriv->settings); int ret = 0; diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 31b379da2ed9..c1b6896d7007 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -272,7 +272,7 @@ static void cisco_stop(struct net_device *dev) int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) { - cisco_proto *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; + cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; const size_t size = sizeof(cisco_proto); cisco_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 8feed459c284..7f450b51a6cb 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1137,7 +1137,7 @@ static void fr_destroy(hdlc_device *hdlc) int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) { - fr_proto *fr_s = ifr->ifr_settings.ifs_ifsu.fr; + fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; const size_t size = sizeof(fr_proto); fr_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index 42690658b146..c41fb70b6929 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -34,7 +34,7 @@ static unsigned short raw_type_trans(struct sk_buff *skb, int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) { - raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; + raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index 4ddc2e08c4ec..b1285cc8fee6 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c @@ -46,7 +46,7 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev) int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) { - raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; + raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); diff --git a/drivers/net/wan/lmc/lmc_ioctl.h b/drivers/net/wan/lmc/lmc_ioctl.h index 38f3c1bca827..57dd861cd3db 100644 --- a/drivers/net/wan/lmc/lmc_ioctl.h +++ b/drivers/net/wan/lmc/lmc_ioctl.h @@ -234,7 +234,7 @@ typedef struct lmc_st1f_control { int command; int address; int value; - char *data; + char __user *data; } lmc_t1f_control; enum lmc_xilinx_c { @@ -246,7 +246,7 @@ enum lmc_xilinx_c { struct lmc_xilinx_control { enum lmc_xilinx_c command; int len; - char *data; + char __user *data; }; /* ------------------ end T1 defs ------------------- */ diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 179b750cc8a8..9dc4a8db2a9f 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -254,7 +254,8 @@ static int n2_close(struct net_device *dev) static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync; + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index 899034164003..0ea4b239e27b 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -204,7 +204,8 @@ static int pci200_close(struct net_device *dev) static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync; + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 4243fea5354d..9fb04ca14cb5 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -733,7 +733,7 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, switch(cmd) { case SIOCGIFNAME: - if (copy_to_user((void *)arg, sl->dev->name, + if (copy_to_user((void __user *)arg, sl->dev->name, strlen(sl->dev->name) + 1)) return -EFAULT; return 0; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 0dea6b1ddd52..9936879eb719 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -539,6 +539,7 @@ struct bus_type pci_bus_type = { .hotplug = pci_hotplug, .suspend = pci_device_suspend, .resume = pci_device_resume, + .dev_attrs = pci_dev_attrs, }; static int __init pci_driver_init(void) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 34161c9f88ff..120a441a88d6 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -23,14 +23,13 @@ /* show configuration fields */ #define pci_config_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf) \ +field##_show(struct device *dev, char *buf) \ { \ struct pci_dev *pdev; \ \ pdev = to_pci_dev (dev); \ return sprintf (buf, format_string, pdev->field); \ -} \ -static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); +} pci_config_attr(vendor, "0x%04x\n"); pci_config_attr(device, "0x%04x\n"); @@ -41,7 +40,7 @@ pci_config_attr(irq, "%u\n"); /* show resources */ static ssize_t -pci_show_resources(struct device * dev, char * buf) +resource_show(struct device * dev, char * buf) { struct pci_dev * pci_dev = to_pci_dev(dev); char * str = buf; @@ -60,7 +59,16 @@ pci_show_resources(struct device * dev, char * buf) return (str - buf); } -static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL); +struct device_attribute pci_dev_attrs[] = { + __ATTR_RO(resource), + __ATTR_RO(vendor), + __ATTR_RO(device), + __ATTR_RO(subsystem_vendor), + __ATTR_RO(subsystem_device), + __ATTR_RO(class), + __ATTR_RO(irq), + __ATTR_NULL, +}; static ssize_t pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) @@ -180,21 +188,10 @@ static struct bin_attribute pcie_config_attr = { void pci_create_sysfs_dev_files (struct pci_dev *pdev) { - struct device *dev = &pdev->dev; - - /* current configuration's attributes */ - device_create_file (dev, &dev_attr_vendor); - device_create_file (dev, &dev_attr_device); - device_create_file (dev, &dev_attr_subsystem_vendor); - device_create_file (dev, &dev_attr_subsystem_device); - device_create_file (dev, &dev_attr_class); - device_create_file (dev, &dev_attr_irq); - device_create_file (dev, &dev_attr_resource); - if (pdev->cfg_size < 4096) - sysfs_create_bin_file(&dev->kobj, &pci_config_attr); + sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); else - sysfs_create_bin_file(&dev->kobj, &pcie_config_attr); + sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); /* add platform-specific attributes */ pcibios_add_platform_entries(pdev); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e1985b618fc9..a9b243770580 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -62,3 +62,4 @@ extern int pci_visit_dev(struct pci_visit *fn, extern spinlock_t pci_bus_lock; extern int pciehp_msi_quirk; +extern struct device_attribute pci_dev_attrs[]; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 6104ca04656c..e54ebde20fa2 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -433,6 +433,14 @@ config SCSI_ATA_PIIX If unsure, say N. +config SCSI_SATA_NV + tristate "NVIDIA SATA support" + depends on SCSI_SATA && PCI && EXPERIMENTAL + help + This option enables support for NVIDIA Serial ATA. + + If unsure, say N. + config SCSI_SATA_PROMISE tristate "Promise SATA TX2/TX4 support" depends on SCSI_SATA && PCI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index fe95ba7809f0..e117d9a616fe 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -127,6 +127,7 @@ obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o +obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index a6588b0f8c98..ff2e7385f59a 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -57,6 +57,7 @@ enum { ich5_pata = 0, ich5_sata = 1, piix4_pata = 2, + ich6_sata = 3, }; static int piix_init_one (struct pci_dev *pdev, @@ -91,10 +92,8 @@ static struct pci_device_id piix_pci_tbl[] = { * and enhanced mode, with queueing and other fancy stuff. * This is distinguished by PCI class code. */ - { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata }, - { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata }, + { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, + { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, { } /* terminate list */ }; @@ -138,7 +137,7 @@ static struct ata_port_operations piix_pata_ops = { .bmdma_setup = ata_bmdma_setup_pio, .bmdma_start = ata_bmdma_start_pio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, @@ -161,7 +160,7 @@ static struct ata_port_operations piix_sata_ops = { .bmdma_setup = ata_bmdma_setup_pio, .bmdma_start = ata_bmdma_start_pio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, @@ -199,6 +198,17 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ .port_ops = &piix_pata_ops, }, + + /* ich6_sata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | + ATA_FLAG_SLAVE_POSS, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &piix_sata_ops, + }, }; static struct pci_bits piix_enable_bits[] = { @@ -327,13 +337,6 @@ static int piix_sata_probe (struct ata_port *ap) static void piix_sata_phy_reset(struct ata_port *ap) { - if (!pci_test_config_bits(ap->host_set->pdev, - &piix_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return; - } - if (!piix_sata_probe(ap)) { ata_port_disable(ap); printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 29dee2c25ba0..d1fadbc4ba78 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -50,7 +50,6 @@ static unsigned int ata_busy_sleep (struct ata_port *ap, unsigned long tmout_pat, unsigned long tmout); static void __ata_dev_select (struct ata_port *ap, unsigned int device); -static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat); static void ata_host_set_pio(struct ata_port *ap); static void ata_host_set_udma(struct ata_port *ap); static void ata_dev_set_pio(struct ata_port *ap, unsigned int device); @@ -65,37 +64,6 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); -static const char * thr_state_name[] = { - "THR_UNKNOWN", - "THR_PORT_RESET", - "THR_AWAIT_DEATH", - "THR_PROBE_FAILED", - "THR_IDLE", - "THR_PROBE_SUCCESS", - "THR_PROBE_START", -}; - -/** - * ata_thr_state_name - convert thread state enum to string - * @thr_state: thread state to be converted to string - * - * Converts the specified thread state id to a constant C string. - * - * LOCKING: - * None. - * - * RETURNS: - * The THR_xxx-prefixed string naming the specified thread - * state id, or the string "<invalid THR_xxx state>". - */ - -static const char *ata_thr_state_name(unsigned int thr_state) -{ - if (thr_state < ARRAY_SIZE(thr_state_name)) - return thr_state_name[thr_state]; - return "<invalid THR_xxx state>"; -} - /** * ata_tf_load_pio - send taskfile registers to host controller * @ap: Port to which output is sent @@ -1150,13 +1118,16 @@ err_out: } /** - * ata_port_reset - - * @ap: + * ata_bus_probe - Reset and probe ATA bus + * @ap: Bus to probe * * LOCKING: + * + * RETURNS: + * Zero on success, non-zero on error. */ -static void ata_port_reset(struct ata_port *ap) +static int ata_bus_probe(struct ata_port *ap) { unsigned int i, found = 0; @@ -1180,14 +1151,12 @@ static void ata_port_reset(struct ata_port *ap) if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out_disable; - ap->thr_state = THR_PROBE_SUCCESS; - - return; + return 0; err_out_disable: ap->ops->port_disable(ap); err_out: - ap->thr_state = THR_PROBE_FAILED; + return -1; } /** @@ -1806,13 +1775,13 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) } /** - * ata_fill_sg - - * @qc: + * ata_fill_sg - Fill PCI IDE PRD table + * @qc: Metadata associated with taskfile to be transferred * * LOCKING: * */ -void ata_fill_sg(struct ata_queued_cmd *qc) +static void ata_fill_sg(struct ata_queued_cmd *qc) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; @@ -1854,6 +1823,21 @@ void ata_fill_sg(struct ata_queued_cmd *qc) } /** + * ata_qc_prep - Prepare taskfile for submission + * @qc: Metadata associated with taskfile to be prepared + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_prep(struct ata_queued_cmd *qc) +{ + if (!(qc->flags & ATA_QCFLAG_SG)) + return; + + ata_fill_sg(qc); +} + +/** * ata_sg_setup_one - * @qc: * @@ -1870,7 +1854,6 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) struct scsi_cmnd *cmd = qc->scsicmd; int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); struct scatterlist *sg = qc->sg; - unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); dma_addr_t dma_address; assert(sg == &qc->sgent); @@ -1880,9 +1863,6 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; sg_dma_len(sg) = cmd->request_bufflen; - if (!have_sg) - return 0; - dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer, cmd->request_bufflen, dir); if (pci_dma_mapping_error(dma_address)) @@ -1912,22 +1892,19 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; struct scsi_cmnd *cmd = qc->scsicmd; struct scatterlist *sg; - int n_elem; - unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); + int n_elem, dir; VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg); assert(cmd->use_sg > 0); sg = (struct scatterlist *)cmd->request_buffer; - if (have_sg) { - int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir); - if (n_elem < 1) - return -1; - DPRINTK("%d sg elements mapped\n", n_elem); - } else { - n_elem = cmd->use_sg; - } + dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir); + if (n_elem < 1) + return -1; + + DPRINTK("%d sg elements mapped\n", n_elem); + qc->n_elem = n_elem; return 0; @@ -2146,8 +2123,8 @@ static void ata_pio_task(void *_data) } /** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active + * ata_qc_timeout - Handle timeout of queued command + * @qc: Command that timed out * * Some part of the kernel (currently, only the SCSI layer) * has noticed that the active command on port @ap has not @@ -2161,23 +2138,15 @@ static void ata_pio_task(void *_data) * transaction completed successfully. * * LOCKING: - * Inherited from SCSI layer (none, can sleep) */ -void ata_eng_timeout(struct ata_port *ap) +static void ata_qc_timeout(struct ata_queued_cmd *qc) { - u8 host_stat, drv_stat; - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; + u8 host_stat = 0, drv_stat; DPRINTK("ENTER\n"); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - goto out; - } - /* hack alert! We cannot use the supplied completion * function from inside the ->eh_strategy_handler() thread. * libata is the only user of ->eh_strategy_handler() in @@ -2187,38 +2156,69 @@ void ata_eng_timeout(struct ata_port *ap) qc->scsidone = scsi_finish_command; switch (qc->tf.protocol) { + case ATA_PROT_DMA: - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + case ATA_PROT_ATAPI_DMA: + host_stat = ata_bmdma_status(ap); - printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n", - ap->id, host_stat); + /* before we do anything else, clear DMA-Start bit */ + ata_bmdma_stop(ap); - ata_dma_complete(qc, host_stat); - break; + /* fall through */ case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + default: + ata_altstatus(ap); + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ + ata_bmdma_ack_irq(ap); - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", + ap->id, qc->tf.command, drv_stat, host_stat); + /* complete taskfile transaction */ ata_qc_complete(qc, drv_stat); break; + } - default: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + DPRINTK("EXIT\n"); +} + +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ + +void ata_eng_timeout(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + DPRINTK("ENTER\n"); - ata_qc_complete(qc, drv_stat); - break; + qc = ata_qc_from_tag(ap, ap->active_tag); + if (!qc) { + printk(KERN_ERR "ata%u: BUG: timeout without command\n", + ap->id); + goto out; } + ata_qc_timeout(qc); + out: DPRINTK("EXIT\n"); } @@ -2316,7 +2316,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) qc->scsidone(cmd); } - qc->flags &= ~ATA_QCFLAG_ACTIVE; + qc->flags = 0; tag = qc->tag; if (likely(ata_tag_valid(tag))) { if (tag == ap->active_tag) @@ -2362,10 +2362,10 @@ int ata_qc_issue(struct ata_queued_cmd *qc) if (ata_sg_setup_one(qc)) goto err_out; } - - ap->ops->fill_sg(qc); } + ap->ops->qc_prep(qc); + qc->ap->active_tag = qc->tag; qc->flags |= ATA_QCFLAG_ACTIVE; @@ -2446,7 +2446,7 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 host_stat, dmactl; + u8 dmactl; void *mmio = (void *) ap->ioaddr.bmdma_addr; /* load PRD table addr. */ @@ -2460,10 +2460,6 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) dmactl |= ATA_DMA_WR; writeb(dmactl, mmio + ATA_DMA_CMD); - /* clear interrupt, error bits */ - host_stat = readb(mmio + ATA_DMA_STATUS); - writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS); - /* issue r/w command */ ap->ops->exec_command(ap, &qc->tf); } @@ -2511,7 +2507,7 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 host_stat, dmactl; + u8 dmactl; /* load PRD table addr. */ outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); @@ -2523,11 +2519,6 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) dmactl |= ATA_DMA_WR; outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - /* clear interrupt, error bits */ - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, - ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - /* issue r/w command */ ap->ops->exec_command(ap, &qc->tf); } @@ -2552,50 +2543,6 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc) } /** - * ata_dma_complete - Complete an active ATA BMDMA command - * @qc: Command to complete - * @host_stat: BMDMA status register contents - * - * LOCKING: - */ - -static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat) -{ - struct ata_port *ap = qc->ap; - VPRINTK("ENTER\n"); - - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - - /* clear start/stop bit */ - writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, - mmio + ATA_DMA_CMD); - - /* ack intr, err bits */ - writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, - mmio + ATA_DMA_STATUS); - } else { - /* clear start/stop bit */ - outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, - ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - - /* ack intr, err bits */ - outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, - ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - } - - - /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_altstatus(ap); /* dummy read */ - - DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n", - ap->id, (u32) host_stat, (u32) ata_chk_status(ap)); - - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap)); -} - -/** * ata_host_intr - Handle host interrupt for given (port, task) * @ap: Port on which interrupt arrived (possibly...) * @qc: Taskfile currently active in engine @@ -2615,59 +2562,60 @@ inline unsigned int ata_host_intr (struct ata_port *ap, struct ata_queued_cmd *qc) { u8 status, host_stat; - unsigned int handled = 0; switch (qc->tf.protocol) { - /* BMDMA completion */ case ATA_PROT_DMA: case ATA_PROT_ATAPI_DMA: - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + /* check status of DMA engine */ + host_stat = ata_bmdma_status(ap); VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat); - if (!(host_stat & ATA_DMA_INTR)) { - ap->stats.idle_irq++; - break; - } + /* if it's not our irq... */ + if (!(host_stat & ATA_DMA_INTR)) + goto idle_irq; - ata_dma_complete(qc, host_stat); - handled = 1; - break; + /* before we do anything else, clear DMA-Start bit */ + ata_bmdma_stop(ap); + + /* fall through */ - /* command completion, but no data xfer */ - /* FIXME: a shared interrupt _will_ cause a non-data command - * to be completed prematurely, with an error. - * - * This doesn't matter right now, since we aren't sending - * non-data commands down this pipe except in development - * situations. - */ - case ATA_PROT_ATAPI: case ATA_PROT_NODATA: - status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + /* check altstatus */ + status = ata_altstatus(ap); + if (status & ATA_BUSY) + goto idle_irq; + + /* check main status, clearing INTRQ */ + status = ata_chk_status(ap); + if (unlikely(status & ATA_BUSY)) + goto idle_irq; + DPRINTK("BUS_NODATA (dev_stat 0x%X)\n", status); + + /* ack bmdma irq events */ + ata_bmdma_ack_irq(ap); + + /* complete taskfile transaction */ ata_qc_complete(qc, status); - handled = 1; break; default: - ap->stats.idle_irq++; + goto idle_irq; + } + + return 1; /* irq handled */ + +idle_irq: + ap->stats.idle_irq++; #ifdef ATA_IRQ_TRAP - if ((ap->stats.idle_irq % 1000) == 0) { - handled = 1; - ata_irq_ack(ap, 0); /* debug trap */ - printk(KERN_WARNING "ata%d: irq trap\n", ap->id); - } -#endif - break; + if ((ap->stats.idle_irq % 1000) == 0) { + handled = 1; + ata_irq_ack(ap, 0); /* debug trap */ + printk(KERN_WARNING "ata%d: irq trap\n", ap->id); } - - return handled; +#endif + return 0; /* irq not handled */ } /** @@ -2701,7 +2649,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) - handled += ata_host_intr(ap, qc); + handled |= ata_host_intr(ap, qc); } } @@ -2711,62 +2659,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) } /** - * ata_thread_iter - - * @ap: - * - * LOCKING: - * - * RETURNS: - * - */ - -static unsigned long ata_thread_iter(struct ata_port *ap) -{ - long timeout = 0; - - DPRINTK("ata%u: thr_state %s\n", - ap->id, ata_thr_state_name(ap->thr_state)); - - switch (ap->thr_state) { - case THR_UNKNOWN: - ap->thr_state = THR_PORT_RESET; - break; - - case THR_PROBE_START: - ap->thr_state = THR_PORT_RESET; - break; - - case THR_PORT_RESET: - ata_port_reset(ap); - break; - - case THR_PROBE_SUCCESS: - up(&ap->probe_sem); - ap->thr_state = THR_IDLE; - break; - - case THR_PROBE_FAILED: - up(&ap->probe_sem); - ap->thr_state = THR_AWAIT_DEATH; - break; - - case THR_AWAIT_DEATH: - case THR_IDLE: - timeout = -1; - break; - - default: - printk(KERN_DEBUG "ata%u: unknown thr state %s\n", - ap->id, ata_thr_state_name(ap->thr_state)); - break; - } - - DPRINTK("ata%u: new thr_state %s, returning %ld\n", - ap->id, ata_thr_state_name(ap->thr_state), timeout); - return timeout; -} - -/** * atapi_packet_task - Write CDB bytes to hardware * @_data: Port to which ATAPI device is attached. * @@ -2847,21 +2739,6 @@ void ata_port_stop (struct ata_port *ap) pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } -static void ata_probe_task(void *_data) -{ - struct ata_port *ap = _data; - long timeout; - - timeout = ata_thread_iter(ap); - if (timeout < 0) - return; - - if (timeout > 0) - queue_delayed_work(ata_wq, &ap->probe_task, timeout); - else - queue_work(ata_wq, &ap->probe_task); -} - /** * ata_host_remove - Unregister SCSI host structure with upper layers * @ap: Port to unregister @@ -2918,7 +2795,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; - ap->thr_state = THR_PROBE_START; ap->cbl = ATA_CBL_NONE; ap->device[0].flags = ATA_DFLAG_MASTER; ap->active_tag = ATA_TAG_POISON; @@ -2926,13 +2802,10 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, INIT_WORK(&ap->packet_task, atapi_packet_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); - INIT_WORK(&ap->probe_task, ata_probe_task, ap); for (i = 0; i < ATA_MAX_DEVICES; i++) ap->device[i].devno = i; - init_MUTEX_LOCKED(&ap->probe_sem); - #ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; @@ -3041,6 +2914,10 @@ int ata_device_add(struct ata_probe_ent *ent) return 0; } + /* TODO: ack irq here, to ensure it won't scream + * when we enable it? + */ + /* obtain irq, that is shared between channels */ if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, DRV_NAME, host_set)) @@ -3055,12 +2932,17 @@ int ata_device_add(struct ata_probe_ent *ent) ap = host_set->ports[i]; DPRINTK("ata%u: probe begin\n", ap->id); - queue_work(ata_wq, &ap->probe_task); /* start probe */ - - DPRINTK("ata%u: probe-wait begin\n", ap->id); - down(&ap->probe_sem); /* wait for end */ + rc = ata_bus_probe(ap); + DPRINTK("ata%u: probe end\n", ap->id); - DPRINTK("ata%u: probe-wait end\n", ap->id); + if (rc) { + /* FIXME: do something useful here? + * Current libata behavior will + * tear down everything when + * the module is removed + * or the h/w is unplugged. + */ + } rc = scsi_add_host(ap->host, &pdev->dev); if (rc) { @@ -3480,7 +3362,7 @@ EXPORT_SYMBOL_GPL(ata_exec_command_mmio); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_interrupt); -EXPORT_SYMBOL_GPL(ata_fill_sg); +EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio); EXPORT_SYMBOL_GPL(ata_bmdma_start_pio); EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index fed311e81c50..1c24c0eefe0e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -182,7 +182,8 @@ int ata_scsi_slave_config(struct scsi_device *sdev) * 65534 when Jens Axboe's patch for dynamically * determining max_sectors is merged. */ - if (dev->flags & ATA_DFLAG_LBA48) { + if ((dev->flags & ATA_DFLAG_LBA48) && + ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { sdev->host->max_sectors = 2048; blk_queue_max_sectors(sdev->request_queue, 2048); } diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c new file mode 100644 index 000000000000..f90821e67cac --- /dev/null +++ b/drivers/scsi/sata_nv.c @@ -0,0 +1,353 @@ +/* + * sata_nv.c - NVIDIA nForce SATA + * + * Copyright 2004 NVIDIA Corp. All rights reserved. + * Copyright 2004 Andrew Chew + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/blkdev.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include "scsi.h" +#include <scsi/scsi_host.h> +#include <linux/libata.h> + +#define DRV_NAME "sata_nv" +#define DRV_VERSION "0.01" + +#define NV_PORTS 2 +#define NV_PIO_MASK 0x1f +#define NV_UDMA_MASK 0x7f +#define NV_PORT0_BMDMA_REG_OFFSET 0x00 +#define NV_PORT1_BMDMA_REG_OFFSET 0x08 +#define NV_PORT0_SCR_REG_OFFSET 0x00 +#define NV_PORT1_SCR_REG_OFFSET 0x40 + +#define NV_INT_STATUS 0x10 +#define NV_INT_STATUS_PDEV_INT 0x01 +#define NV_INT_STATUS_PDEV_PM 0x02 +#define NV_INT_STATUS_PDEV_ADDED 0x04 +#define NV_INT_STATUS_PDEV_REMOVED 0x08 +#define NV_INT_STATUS_SDEV_INT 0x10 +#define NV_INT_STATUS_SDEV_PM 0x20 +#define NV_INT_STATUS_SDEV_ADDED 0x40 +#define NV_INT_STATUS_SDEV_REMOVED 0x80 +#define NV_INT_STATUS_PDEV_HOTPLUG (NV_INT_STATUS_PDEV_ADDED | \ + NV_INT_STATUS_PDEV_REMOVED) +#define NV_INT_STATUS_SDEV_HOTPLUG (NV_INT_STATUS_SDEV_ADDED | \ + NV_INT_STATUS_SDEV_REMOVED) +#define NV_INT_STATUS_HOTPLUG (NV_INT_STATUS_PDEV_HOTPLUG | \ + NV_INT_STATUS_SDEV_HOTPLUG) + +#define NV_INT_ENABLE 0x11 +#define NV_INT_ENABLE_PDEV_MASK 0x01 +#define NV_INT_ENABLE_PDEV_PM 0x02 +#define NV_INT_ENABLE_PDEV_ADDED 0x04 +#define NV_INT_ENABLE_PDEV_REMOVED 0x08 +#define NV_INT_ENABLE_SDEV_MASK 0x10 +#define NV_INT_ENABLE_SDEV_PM 0x20 +#define NV_INT_ENABLE_SDEV_ADDED 0x40 +#define NV_INT_ENABLE_SDEV_REMOVED 0x80 +#define NV_INT_ENABLE_PDEV_HOTPLUG (NV_INT_ENABLE_PDEV_ADDED | \ + NV_INT_ENABLE_PDEV_REMOVED) +#define NV_INT_ENABLE_SDEV_HOTPLUG (NV_INT_ENABLE_SDEV_ADDED | \ + NV_INT_ENABLE_SDEV_REMOVED) +#define NV_INT_ENABLE_HOTPLUG (NV_INT_ENABLE_PDEV_HOTPLUG | \ + NV_INT_ENABLE_SDEV_HOTPLUG) + +#define NV_INT_CONFIG 0x12 +#define NV_INT_CONFIG_METHD 0x01 // 0 = INT, 1 = SMI + +static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); +static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static void nv_host_stop (struct ata_host_set *host_set); + +static struct pci_device_id nv_pci_tbl[] = { + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, + PCI_ANY_ID, PCI_ANY_ID, }, + { 0, } /* terminate list */ +}; + +static struct pci_driver nv_pci_driver = { + .name = DRV_NAME, + .id_table = nv_pci_tbl, + .probe = nv_init_one, + .remove = ata_pci_remove_one, +}; + +static Scsi_Host_Template nv_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = ATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations nv_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .exec_command = ata_exec_command_pio, + .check_status = ata_check_status_pio, + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup_pio, + .bmdma_start = ata_bmdma_start_pio, + .qc_prep = ata_qc_prep, + .eng_timeout = ata_eng_timeout, + .irq_handler = nv_interrupt, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = nv_host_stop, +}; + +MODULE_AUTHOR("NVIDIA"); +MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, nv_pci_tbl); + +irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + unsigned int i; + unsigned int handled = 0; + unsigned long flags; + u8 intr_status; + u8 intr_enable; + + spin_lock_irqsave(&host_set->lock, flags); + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap; + + ap = host_set->ports[i]; + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && (!(qc->tf.ctl & ATA_NIEN))) + handled += ata_host_intr(ap, qc); + } + + intr_status = inb(ap->ioaddr.scr_addr + NV_INT_STATUS); + intr_enable = inb(ap->ioaddr.scr_addr + NV_INT_ENABLE); + + // Clear interrupt status. + outb(0xff, ap->ioaddr.scr_addr + NV_INT_STATUS); + + if (intr_status & NV_INT_STATUS_HOTPLUG) { + if (intr_status & NV_INT_STATUS_PDEV_ADDED) { + printk(KERN_WARNING "ata%u: " + "Primary device added\n", ap->id); + } + + if (intr_status & NV_INT_STATUS_PDEV_REMOVED) { + printk(KERN_WARNING "ata%u: " + "Primary device removed\n", ap->id); + } + + if (intr_status & NV_INT_STATUS_SDEV_ADDED) { + printk(KERN_WARNING "ata%u: " + "Secondary device added\n", ap->id); + } + + if (intr_status & NV_INT_STATUS_SDEV_REMOVED) { + printk(KERN_WARNING "ata%u: " + "Secondary device removed\n", ap->id); + } + } + } + + spin_unlock_irqrestore(&host_set->lock, flags); + + return IRQ_RETVAL(handled); +} + +static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + if (sc_reg > SCR_CONTROL) + return 0xffffffffU; + + return inl(ap->ioaddr.scr_addr + (sc_reg * 4)); +} + +static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +{ + if (sc_reg > SCR_CONTROL) + return; + + outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); +} + +static void nv_host_stop (struct ata_host_set *host_set) +{ + int i; + + for (i=0; i<host_set->n_ports; i++) { + u8 intr_mask; + + // Disable hotplug event interrupts. + intr_mask = inb(host_set->ports[i]->ioaddr.scr_addr + + NV_INT_ENABLE); + intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); + outb(intr_mask, host_set->ports[i]->ioaddr.scr_addr + + NV_INT_ENABLE); + } +} + +static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version = 0; + struct ata_probe_ent *probe_ent = NULL; + int i; + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + INIT_LIST_HEAD(&probe_ent->node); + + probe_ent->pdev = pdev; + probe_ent->sht = &nv_sht; + probe_ent->host_flags = ATA_FLAG_SATA | + ATA_FLAG_SATA_RESET | + ATA_FLAG_SRST | + ATA_FLAG_NO_LEGACY; + probe_ent->port_ops = &nv_ops; + probe_ent->n_ports = NV_PORTS; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->pio_mask = NV_PIO_MASK; + probe_ent->udma_mask = NV_UDMA_MASK; + + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); + ata_std_ports(&probe_ent->port[0]); + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + probe_ent->port[0].bmdma_addr = + pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET; + probe_ent->port[0].scr_addr = + pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET; + + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); + ata_std_ports(&probe_ent->port[1]); + probe_ent->port[1].altstatus_addr = + probe_ent->port[1].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[1].bmdma_addr = + pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET; + probe_ent->port[1].scr_addr = + pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET; + + pci_set_master(pdev); + + rc = ata_device_add(probe_ent); + if (rc != NV_PORTS) + goto err_out_regions; + + // Enable hotplug event interrupts. + for (i=0; i<probe_ent->n_ports; i++) { + u8 intr_mask; + + outb(NV_INT_STATUS_HOTPLUG, probe_ent->port[i].scr_addr + + NV_INT_STATUS); + + intr_mask = inb(probe_ent->port[i].scr_addr + NV_INT_ENABLE); + intr_mask |= NV_INT_ENABLE_HOTPLUG; + outb(intr_mask, probe_ent->port[i].scr_addr + NV_INT_ENABLE); + } + + kfree(probe_ent); + + return 0; + +err_out_regions: + pci_release_regions(pdev); + +err_out: + pci_disable_device(pdev); + return rc; +} + +static int __init nv_init(void) +{ + return pci_module_init(&nv_pci_driver); +} + +static void __exit nv_exit(void) +{ + pci_unregister_driver(&nv_pci_driver); +} + +module_init(nv_init); +module_exit(nv_exit); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 268b2c345728..ae6d77c96786 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -81,7 +81,7 @@ static void pdc_eng_timeout(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap); static void pdc_phy_reset(struct ata_port *ap); -static void pdc_fill_sg(struct ata_queued_cmd *qc); +static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); static inline void pdc_dma_complete (struct ata_port *ap, @@ -114,7 +114,7 @@ static struct ata_port_operations pdc_sata_ops = { .phy_reset = pdc_phy_reset, .bmdma_setup = pdc_dma_setup, .bmdma_start = pdc_dma_start, - .fill_sg = pdc_fill_sg, + .qc_prep = pdc_qc_prep, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc_interrupt, .scr_read = pdc_sata_scr_read, @@ -261,14 +261,14 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void pdc_fill_sg(struct ata_queued_cmd *qc) +static void pdc_qc_prep(struct ata_queued_cmd *qc) { struct pdc_port_priv *pp = qc->ap->private_data; unsigned int i; VPRINTK("ENTER\n"); - ata_fill_sg(qc); + ata_qc_prep(qc); i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt); diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 33ae676e2d78..12043e8f84cb 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -131,7 +131,7 @@ static struct ata_port_operations sil_ops = { .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup_mmio, .bmdma_start = ata_bmdma_start_mmio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .scr_read = sil_scr_read, @@ -302,6 +302,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) ap->id, dev->devno); ap->host->max_sectors = 15; ap->host->hostt->max_sectors = 15; + dev->flags |= ATA_DFLAG_LOCK_SECTORS; return; } diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 8965ee281839..a2106d2ebb18 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -100,7 +100,7 @@ static struct ata_port_operations sis_ops = { .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup_pio, .bmdma_start = ata_bmdma_start_pio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .scr_read = sis_scr_read, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 60841abc4398..af28b1f7a95f 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -233,7 +233,7 @@ static struct ata_port_operations k2_sata_ops = { .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup_mmio, .bmdma_start = ata_bmdma_start_mmio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .scr_read = k2_sata_scr_read, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 3268fdf7e583..ea8ddcc78a6d 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -153,7 +153,7 @@ static void pdc_eng_timeout(struct ata_port *ap); static void pdc_20621_phy_reset (struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap); -static void pdc20621_fill_sg(struct ata_queued_cmd *qc); +static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc20621_host_stop(struct ata_host_set *host_set); @@ -200,7 +200,7 @@ static struct ata_port_operations pdc_20621_ops = { .phy_reset = pdc_20621_phy_reset, .bmdma_setup = pdc20621_dma_setup, .bmdma_start = pdc20621_dma_start, - .fill_sg = pdc20621_fill_sg, + .qc_prep = pdc20621_qc_prep, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc20621_interrupt, .port_start = pdc_port_start, @@ -434,7 +434,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, buf32[dw + 3]); } -static void pdc20621_fill_sg(struct ata_queued_cmd *qc) +static void pdc20621_qc_prep(struct ata_queued_cmd *qc) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; @@ -446,6 +446,9 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) unsigned int i, last, idx, total_len = 0, sgt_len; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; + if (!(qc->flags & ATA_QCFLAG_SG)) + return; + VPRINTK("ata%u: ENTER\n", ap->id); /* hard-code chip #0 */ diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 46d385128842..84ee429471ce 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -108,7 +108,7 @@ static struct ata_port_operations svia_sata_ops = { .bmdma_setup = ata_bmdma_setup_pio, .bmdma_start = ata_bmdma_start_pio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index e0ad17121850..a09f03ee0ef0 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -215,7 +215,7 @@ static struct ata_port_operations vsc_sata_ops = { .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup_mmio, .bmdma_start = ata_bmdma_start_mmio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, .eng_timeout = ata_eng_timeout, .irq_handler = vsc_sata_interrupt, .scr_read = vsc_sata_scr_read, diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d291d68cd1b0..4067ba593d9c 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1404,7 +1404,7 @@ static ssize_t sdebug_delay_store(struct device_driver * ddp, return -EINVAL; } DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, - sdebug_delay_store) + sdebug_delay_store); static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) { @@ -1433,7 +1433,7 @@ opts_done: return count; } DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, - sdebug_opts_store) + sdebug_opts_store); static ssize_t sdebug_ptype_show(struct device_driver * ddp, char * buf) { @@ -1450,7 +1450,7 @@ static ssize_t sdebug_ptype_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store) +DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store); static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) { @@ -1469,19 +1469,19 @@ static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, return -EINVAL; } DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show, - sdebug_num_tgts_store) + sdebug_num_tgts_store); static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); } -DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) +DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL); static ssize_t sdebug_num_parts_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts); } -DRIVER_ATTR(num_parts, S_IRUGO, sdebug_num_parts_show, NULL) +DRIVER_ATTR(num_parts, S_IRUGO, sdebug_num_parts_show, NULL); static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) { @@ -1500,7 +1500,7 @@ static ssize_t sdebug_every_nth_store(struct device_driver * ddp, return -EINVAL; } DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show, - sdebug_every_nth_store) + sdebug_every_nth_store); static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) { @@ -1519,13 +1519,13 @@ static ssize_t sdebug_max_luns_store(struct device_driver * ddp, return -EINVAL; } DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show, - sdebug_max_luns_store) + sdebug_max_luns_store); static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); } -DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) +DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL); static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) { @@ -1562,7 +1562,7 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp, return count; } DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, - sdebug_add_host_store) + sdebug_add_host_store); static void do_create_driverfs_files(void) { diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index fceb6f9a1be1..a9ff002bb0a5 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -99,7 +99,7 @@ show_##name (struct class_device *class_dev, char *buf) \ */ #define shost_rd_attr2(name, field, format_string) \ shost_show_function(name, field, format_string) \ -static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); #define shost_rd_attr(field, format_string) \ shost_rd_attr2(field, field, format_string) @@ -228,8 +228,8 @@ sdev_show_##field (struct device *dev, char *buf) \ * read only field. */ #define sdev_rd_attr(field, format_string) \ - sdev_show_function(field, format_string) \ -static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL) + sdev_show_function(field, format_string) \ +static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL); /* @@ -247,7 +247,7 @@ sdev_store_##field (struct device *dev, const char *buf, size_t count) \ snscanf (buf, 20, format_string, &sdev->field); \ return count; \ } \ -static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field) +static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field); /* Currently we don't export bit fields, but we might in future, * so leave this code in */ @@ -272,7 +272,7 @@ sdev_store_##field (struct device *dev, const char *buf, size_t count) \ } \ return ret; \ } \ -static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field) +static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field); /* * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1", @@ -320,7 +320,7 @@ sdev_store_timeout (struct device *dev, const char *buf, size_t count) sdev->timeout = timeout * HZ; return count; } -static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout) +static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout); static ssize_t store_rescan_field (struct device *dev, const char *buf, size_t count) @@ -328,7 +328,7 @@ store_rescan_field (struct device *dev, const char *buf, size_t count) scsi_rescan_device(dev); return count; } -static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field) +static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field); static ssize_t sdev_store_delete(struct device *dev, const char *buf, size_t count) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 3b30baff2000..9c41eefb9640 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -152,7 +152,7 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ spi_transport_store_function(field, format_string) \ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ show_spi_transport_##field, \ - store_spi_transport_##field) + store_spi_transport_##field); /* The Parallel SCSI Tranport Attributes: */ spi_transport_rd_attr(offset, "%d\n"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index e5ce98eb0378..cb005e5a5bca 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -603,5 +603,28 @@ config SERIAL_PMACZILOG_CONSOLE on your PowerMac as the console, you can do so by answering Y to this option. +config SERIAL_LH7A40X + tristate "Sharp LH7A40X embedded UART support" + depends on ARM && ARCH_LH7A40X + select SERIAL_CORE + help + This enables support for the three on-board UARTs of the + Sharp LH7A40X series CPUs. Choose Y or M. + +config SERIAL_LH7A40X_CONSOLE + bool "Support for connsole on Sharp LH7A40X serial port" + depends on SERIAL_LH7A40X=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use one of the serial ports as the + system console--the system console is the device which + receives all kernel messages and warnings and which allows + logins in single user mode. + + Even if you say Y here, the currently visible framebuffer console + (/dev/tty0) will still be used as the default system console, but + you can alter that using a kernel command line, for example + "console=ttyAM1". + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index c2eb159d8b43..ceacc99d8cd1 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_V850E_UART) += v850e_uart.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o +obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index e83bb0728a37..cb6b4f3ec5c9 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -35,6 +35,7 @@ #include <linux/circ_buf.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/device.h> #include <asm/io.h> #include <asm/hardware.h> @@ -804,26 +805,76 @@ static struct uart_driver serial_pxa_reg = { .cons = PXA_CONSOLE, }; -static int __init serial_pxa_init(void) +static int serial_pxa_suspend(struct device *_dev, u32 state, u32 level) { - int i, ret; + struct uart_pxa_port *sport = dev_get_drvdata(_dev); - ret = uart_register_driver(&serial_pxa_reg); - if (ret) - return ret; + if (sport && level == SUSPEND_DISABLE) + uart_suspend_port(&serial_pxa_reg, &sport->port); + + return 0; +} - for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++) - uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port); +static int serial_pxa_resume(struct device *_dev, u32 level) +{ + struct uart_pxa_port *sport = dev_get_drvdata(_dev); + + if (sport && level == RESUME_ENABLE) + uart_resume_port(&serial_pxa_reg, &sport->port); + + return 0; +} +static int serial_pxa_probe(struct device *_dev) +{ + struct platform_device *dev = to_platform_device(_dev); + + serial_pxa_ports[dev->id].port.dev = _dev; + uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port); + dev_set_drvdata(_dev, &serial_pxa_ports[dev->id]); return 0; } -static void __exit serial_pxa_exit(void) +static int serial_pxa_remove(struct device *_dev) { - int i; + struct uart_pxa_port *sport = dev_get_drvdata(_dev); + + dev_set_drvdata(_dev, NULL); - for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++) - uart_remove_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port); + if (sport) + uart_remove_one_port(&serial_pxa_reg, &sport->port); + + return 0; +} + +static struct device_driver serial_pxa_driver = { + .name = "pxa2xx-uart", + .bus = &platform_bus_type, + .probe = serial_pxa_probe, + .remove = serial_pxa_remove, + + .suspend = serial_pxa_suspend, + .resume = serial_pxa_resume, +}; + +int __init serial_pxa_init(void) +{ + int ret; + + ret = uart_register_driver(&serial_pxa_reg); + if (ret != 0) + return ret; + + ret = driver_register(&serial_pxa_driver); + if (ret != 0) + uart_unregister_driver(&serial_pxa_reg); + + return ret; +} + +void __exit serial_pxa_exit(void) +{ + driver_unregister(&serial_pxa_driver); uart_unregister_driver(&serial_pxa_reg); } diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c new file mode 100644 index 000000000000..d863368e45e2 --- /dev/null +++ b/drivers/serial/serial_lh7a40x.c @@ -0,0 +1,708 @@ +/* drivers/serial/serial_lh7a40x.c + * + * Copyright (C) 2004 Coastal Environmental Systems + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ + +/* Driver for Sharp LH7A40X embedded serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd. + * + * --- + * + * This driver supports the embedded UARTs of the Sharp LH7A40X series + * CPUs. While similar to the 16550 and other UART chips, there is + * nothing close to register compatibility. Moreover, some of the + * modem control lines are not available, either in the chip or they + * are lacking in the board-level implementation. + * + * - Use of SIRDIS + * For simplicity, we disable the IR functions of any UART whenever + * we enable it. + * + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/serial.h> +#include <linux/console.h> +#include <linux/sysrq.h> + +#include <asm/io.h> +#include <asm/irq.h> + +#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/serial_core.h> + +#include <asm/arch/serial.h> + +#define DEV_MAJOR 204 +#define DEV_MINOR 16 +#define DEV_NR 3 + +#define ISR_LOOP_LIMIT 256 + +#define UR(p,o) _UR ((p)->membase, o) +#define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o)))) +#define BIT_CLR(p,o,m) UR(p,o) = UR(p,o) & (~(unsigned int)m) +#define BIT_SET(p,o,m) UR(p,o) = UR(p,o) | ( (unsigned int)m) + +#define UART_REG_SIZE 32 + +#define UARTEN (0x01) /* UART enable */ +#define SIRDIS (0x02) /* Serial IR disable (UART1 only) */ + +#define RxEmpty (0x10) +#define TxEmpty (0x80) +#define TxFull (0x20) +#define nRxRdy RxEmpty +#define nTxRdy TxFull +#define TxBusy (0x08) + +#define RxBreak (0x0800) +#define RxOverrunError (0x0400) +#define RxParityError (0x0200) +#define RxFramingError (0x0100) +#define RxError (RxBreak | RxOverrunError | RxParityError | RxFramingError) + +#define DCD (0x04) +#define DSR (0x02) +#define CTS (0x01) + +#define RxInt (0x01) +#define TxInt (0x02) +#define ModemInt (0x04) +#define RxTimeoutInt (0x08) + +#define MSEOI (0x10) + +#define WLEN_8 (0x60) +#define WLEN_7 (0x40) +#define WLEN_6 (0x20) +#define WLEN_5 (0x00) +#define WLEN (0x60) /* Mask for all word-length bits */ +#define STP2 (0x08) +#define PEN (0x02) /* Parity Enable */ +#define EPS (0x04) /* Even Parity Set */ +#define FEN (0x10) /* FIFO Enable */ +#define BRK (0x01) /* Send Break */ + + +struct uart_port_lh7a40x { + struct uart_port port; + unsigned int statusPrev; /* Most recently read modem status */ +}; + +static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop) +{ + BIT_CLR (port, UART_R_INTEN, TxInt); +} + +static void lh7a40xuart_start_tx (struct uart_port* port, + unsigned int tty_start) +{ + BIT_SET (port, UART_R_INTEN, TxInt); + + /* *** FIXME: do I need to check for startup of the + transmitter? The old driver did, but AMBA + doesn't . */ +} + +static void lh7a40xuart_stop_rx (struct uart_port* port) +{ + BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); +} + +static void lh7a40xuart_enable_ms (struct uart_port* port) +{ + BIT_SET (port, UART_R_INTEN, ModemInt); +} + +static void +#ifdef SUPPORT_SYSRQ +lh7a40xuart_rx_chars (struct uart_port* port, struct pt_regs* regs) +#else +lh7a40xuart_rx_chars (struct uart_port* port) +#endif +{ + struct tty_struct* tty = port->info->tty; + int cbRxMax = 256; /* (Gross) limit on receive */ + unsigned int data; /* Received data and status */ + + while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty->flip.work.func((void*)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + printk(KERN_WARNING "TTY_DONT_FLIP set\n"); + return; + } + } + + data = UR (port, UART_R_DATA); + + *tty->flip.char_buf_ptr = (unsigned char) data; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + ++port->icount.rx; + + if (data & RxError) { /* Quick check, short-circuit */ + if (data & RxBreak) { + data &= ~(RxFramingError | RxParityError); + ++port->icount.brk; + if (uart_handle_break (port)) + continue; + } + else if (data & RxParityError) + ++port->icount.parity; + else if (data & RxFramingError) + ++port->icount.frame; + if (data & RxOverrunError) + ++port->icount.overrun; + + /* Mask by termios, leave Rx'd byte */ + data &= port->read_status_mask | 0xff; + + if (data & RxBreak) + *tty->flip.flag_buf_ptr = TTY_BREAK; + else if (data & RxParityError) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (data & RxFramingError) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + + if (uart_handle_sysrq_char (port, (unsigned char) data, regs)) + continue; + + if ((data & port->ignore_status_mask) == 0) { + ++tty->flip.flag_buf_ptr; + ++tty->flip.char_buf_ptr; + ++tty->flip.count; + } + if ((data & RxOverrunError) + && tty->flip.count < TTY_FLIPBUF_SIZE) { + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character + */ + *tty->flip.char_buf_ptr++ = 0; + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + ++tty->flip.count; + } + } + tty_flip_buffer_push (tty); + return; +} + +static void lh7a40xuart_tx_chars (struct uart_port* port) +{ + struct circ_buf* xmit = &port->info->xmit; + int cbTxMax = port->fifosize; + + if (port->x_char) { + UR (port, UART_R_DATA) = port->x_char; + ++port->icount.tx; + port->x_char = 0; + return; + } + if (uart_circ_empty (xmit) || uart_tx_stopped (port)) { + lh7a40xuart_stop_tx (port, 0); + return; + } + + /* Unlike the AMBA UART, the lh7a40x UART does not guarantee + that at least half of the FIFO is empty. Instead, we check + status for every character. Using the AMBA method causes + the transmitter to drop characters. */ + + do { + UR (port, UART_R_DATA) = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + ++port->icount.tx; + if (uart_circ_empty(xmit)) + break; + } while (!(UR (port, UART_R_STATUS) & nTxRdy) + && cbTxMax--); + + if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) + uart_write_wakeup (port); + + if (uart_circ_empty (xmit)) + lh7a40xuart_stop_tx (port, 0); +} + +static void lh7a40xuart_modem_status (struct uart_port* port) +{ + unsigned int status = UR (port, UART_R_STATUS); + unsigned int delta + = status ^ ((struct uart_port_lh7a40x*) port)->statusPrev; + + BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */ + + if (!delta) /* Only happens if we missed 2 transitions */ + return; + + ((struct uart_port_lh7a40x*) port)->statusPrev = status; + + if (delta & DCD) + uart_handle_dcd_change (port, status & DCD); + + if (delta & DSR) + ++port->icount.dsr; + + if (delta & CTS) + uart_handle_cts_change (port, status & CTS); + + wake_up_interruptible (&port->info->delta_msr_wait); +} + +static irqreturn_t lh7a40xuart_int (int irq, void* dev_id, + struct pt_regs* regs) +{ + struct uart_port* port = dev_id; + unsigned int cLoopLimit = ISR_LOOP_LIMIT; + unsigned int isr = UR (port, UART_R_ISR); + + + do { + if (isr & (RxInt | RxTimeoutInt)) +#ifdef SUPPORT_SYSRQ + lh7a40xuart_rx_chars(port, regs); +#else + lh7a40xuart_rx_chars(port); +#endif + if (isr & ModemInt) + lh7a40xuart_modem_status (port); + if (isr & TxInt) + lh7a40xuart_tx_chars (port); + + if (--cLoopLimit == 0) + break; + + isr = UR (port, UART_R_ISR); + } while (isr & (RxInt | TxInt | RxTimeoutInt)); + + return IRQ_HANDLED; +} + +static unsigned int lh7a40xuart_tx_empty (struct uart_port* port) +{ + return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0; +} + +static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port) +{ + unsigned int result = 0; + unsigned int status = UR (port, UART_R_STATUS); + + if (status & DCD) + result |= TIOCM_CAR; + if (status & DSR) + result |= TIOCM_DSR; + if (status & CTS) + result |= TIOCM_CTS; + + return result; +} + +static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl) +{ + /* None of the ports supports DTR. UART1 supports RTS through GPIO. */ + /* Note, kernel appears to be setting DTR and RTS on console. */ + + /* *** FIXME: this deserves more work. There's some work in + tracing all of the IO pins. */ +#if 0 + if( port->mapbase == UART1_PHYS) { + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + if (mctrl & TIOCM_RTS) + gpio->pbdr &= ~GPIOB_UART1_RTS; + else + gpio->pbdr |= GPIOB_UART1_RTS; + } +#endif +} + +static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state) +{ + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + if (break_state == -1) + BIT_SET (port, UART_R_FCON, BRK); /* Assert break */ + else + BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */ + spin_unlock_irqrestore(&port->lock, flags); +} + +static int lh7a40xuart_startup (struct uart_port* port) +{ + int retval; + + retval = request_irq (port->irq, lh7a40xuart_int, 0, + "serial_lh7a40x", port); + if (retval) + return retval; + + /* Initial modem control-line settings */ + ((struct uart_port_lh7a40x*) port)->statusPrev + = UR (port, UART_R_STATUS); + + /* There is presently no configuration option to enable IR. + Thus, we always disable it. */ + + BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); + BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); + + return 0; +} + +static void lh7a40xuart_shutdown (struct uart_port* port) +{ + free_irq (port->irq, port); + BIT_CLR (port, UART_R_FCON, BRK | FEN); + BIT_CLR (port, UART_R_CON, UARTEN); +} + +static void lh7a40xuart_set_termios (struct uart_port* port, + struct termios* termios, + struct termios* old) +{ + unsigned int con; + unsigned int inten; + unsigned int fcon; + unsigned long flags; + unsigned int baud; + unsigned int quot; + + baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16); + quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */ + + switch (termios->c_cflag & CSIZE) { + case CS5: + fcon = WLEN_5; + break; + case CS6: + fcon = WLEN_6; + break; + case CS7: + fcon = WLEN_7; + break; + case CS8: + default: + fcon = WLEN_8; + break; + } + if (termios->c_cflag & CSTOPB) + fcon |= STP2; + if (termios->c_cflag & PARENB) { + fcon |= PEN; + if (!(termios->c_cflag & PARODD)) + fcon |= EPS; + } + if (port->fifosize > 1) + fcon |= FEN; + + spin_lock_irqsave (&port->lock, flags); + + uart_update_timeout (port, termios->c_cflag, baud); + + port->read_status_mask = RxOverrunError; + if (termios->c_iflag & INPCK) + port->read_status_mask |= RxFramingError | RxParityError; + if (termios->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= RxBreak; + + /* Figure mask for status we ignore */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= RxFramingError | RxParityError; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= RxBreak; + /* Ignore overrun when ignorning parity */ + /* *** FIXME: is this in the right place? */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= RxOverrunError; + } + + /* Ignore all receive errors when receive disabled */ + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= RxError; + + con = UR (port, UART_R_CON); + inten = (UR (port, UART_R_INTEN) & ~ModemInt); + + if (UART_ENABLE_MS (port, termios->c_cflag)) + inten |= ModemInt; + + BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */ + UR (port, UART_R_INTEN) = 0; /* Disable interrupts */ + UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */ + UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */ + UR (port, UART_R_INTEN) = inten; /* Enable interrupts */ + UR (port, UART_R_CON) = con; /* Restore UART mode */ + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char* lh7a40xuart_type (struct uart_port* port) +{ + return port->type == PORT_LH7A40X ? "LH7A40X" : NULL; +} + +static void lh7a40xuart_release_port (struct uart_port* port) +{ + release_mem_region (port->mapbase, UART_REG_SIZE); +} + +static int lh7a40xuart_request_port (struct uart_port* port) +{ + return request_mem_region (port->mapbase, UART_REG_SIZE, + "serial_lh7a40x") != NULL + ? 0 : -EBUSY; +} + +static void lh7a40xuart_config_port (struct uart_port* port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + port->type = PORT_LH7A40X; + lh7a40xuart_request_port (port); + } +} + +static int lh7a40xuart_verify_port (struct uart_port* port, + struct serial_struct* ser) +{ + int ret = 0; + + if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X) + ret = -EINVAL; + if (ser->irq < 0 || ser->irq >= NR_IRQS) + ret = -EINVAL; + if (ser->baud_base < 9600) /* *** FIXME: is this true? */ + ret = -EINVAL; + return ret; +} + +static struct uart_ops lh7a40x_uart_ops = { + .tx_empty = lh7a40xuart_tx_empty, + .set_mctrl = lh7a40xuart_set_mctrl, + .get_mctrl = lh7a40xuart_get_mctrl, + .stop_tx = lh7a40xuart_stop_tx, + .start_tx = lh7a40xuart_start_tx, + .stop_rx = lh7a40xuart_stop_rx, + .enable_ms = lh7a40xuart_enable_ms, + .break_ctl = lh7a40xuart_break_ctl, + .startup = lh7a40xuart_startup, + .shutdown = lh7a40xuart_shutdown, + .set_termios = lh7a40xuart_set_termios, + .type = lh7a40xuart_type, + .release_port = lh7a40xuart_release_port, + .request_port = lh7a40xuart_request_port, + .config_port = lh7a40xuart_config_port, + .verify_port = lh7a40xuart_verify_port, +}; + +static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { + { + .port = { + .membase = (void*) io_p2v (UART1_PHYS), + .mapbase = UART1_PHYS, + .iotype = SERIAL_IO_MEM, + .irq = IRQ_UART1INTR, + .uartclk = 14745600/2, + .fifosize = 16, + .ops = &lh7a40x_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + }, + { + .port = { + .membase = (void*) io_p2v (UART2_PHYS), + .mapbase = UART2_PHYS, + .iotype = SERIAL_IO_MEM, + .irq = IRQ_UART2INTR, + .uartclk = 14745600/2, + .fifosize = 16, + .ops = &lh7a40x_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 1, + }, + }, + { + .port = { + .membase = (void*) io_p2v (UART3_PHYS), + .mapbase = UART3_PHYS, + .iotype = SERIAL_IO_MEM, + .irq = IRQ_UART3INTR, + .uartclk = 14745600/2, + .fifosize = 16, + .ops = &lh7a40x_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 2, + }, + }, +}; + +#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE +# define LH7A40X_CONSOLE NULL +#else +# define LH7A40X_CONSOLE &lh7a40x_console + + +static void lh7a40xuart_console_write (struct console* co, + const char* s, + unsigned int count) +{ + struct uart_port* port = &lh7a40x_ports[co->index].port; + unsigned int con = UR (port, UART_R_CON); + unsigned int inten = UR (port, UART_R_INTEN); + + + UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ + BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ + + for (; count-- > 0; ++s) { + while (UR (port, UART_R_STATUS) & nTxRdy) + ; + UR (port, UART_R_DATA) = *s; + if (*s == '\n') { + while ((UR (port, UART_R_STATUS) & TxBusy)) + ; + UR (port, UART_R_DATA) = '\r'; + } + } + + /* Wait until all characters are sent */ + while (UR (port, UART_R_STATUS) & TxBusy) + ; + + /* Restore control and interrupt mask */ + UR (port, UART_R_CON) = con; + UR (port, UART_R_INTEN) = inten; +} + +static void __init lh7a40xuart_console_get_options (struct uart_port* port, + int* baud, + int* parity, + int* bits) +{ + if (UR (port, UART_R_CON) & UARTEN) { + unsigned int fcon = UR (port, UART_R_FCON); + unsigned int quot = UR (port, UART_R_BRCON) + 1; + + switch (fcon & (PEN | EPS)) { + default: *parity = 'n'; break; + case PEN: *parity = 'o'; break; + case PEN | EPS: *parity = 'e'; break; + } + + switch (fcon & WLEN) { + default: + case WLEN_8: *bits = 8; break; + case WLEN_7: *bits = 7; break; + case WLEN_6: *bits = 6; break; + case WLEN_5: *bits = 5; break; + } + + *baud = port->uartclk/(16*quot); + } +} + +static int __init lh7a40xuart_console_setup (struct console* co, char* options) +{ + struct uart_port* port; + int baud = 38400; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index >= DEV_NR) /* Bounds check on device number */ + co->index = 0; + port = &lh7a40x_ports[co->index].port; + + if (options) + uart_parse_options (options, &baud, &parity, &bits, &flow); + else + lh7a40xuart_console_get_options (port, &baud, &parity, &bits); + + return uart_set_options (port, co, baud, parity, bits, flow); +} + +extern struct uart_driver lh7a40x_reg; +static struct console lh7a40x_console = { + .name = "ttyAM", + .write = lh7a40xuart_console_write, + .device = uart_console_device, + .setup = lh7a40xuart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &lh7a40x_reg, +}; + +static int __init lh7a40xuart_console_init(void) +{ + register_console (&lh7a40x_console); + return 0; +} + +console_initcall (lh7a40xuart_console_init); + +#endif + +static struct uart_driver lh7a40x_reg = { + .owner = THIS_MODULE, + .driver_name = "ttyAM", + .dev_name = "ttyAM", + .major = DEV_MAJOR, + .minor = DEV_MINOR, + .nr = DEV_NR, + .cons = LH7A40X_CONSOLE, +}; + +static int __init lh7a40xuart_init(void) +{ + int ret; + + printk (KERN_INFO "serial: LH7A40X serial driver\n"); + + ret = uart_register_driver (&lh7a40x_reg); + + if (ret == 0) { + int i; + + for (i = 0; i < DEV_NR; i++) + uart_add_one_port (&lh7a40x_reg, + &lh7a40x_ports[i].port); + } + return ret; +} + +static void __exit lh7a40xuart_exit(void) +{ + int i; + + for (i = 0; i < DEV_NR; i++) + uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port); + + uart_unregister_driver (&lh7a40x_reg); +} + +module_init (lh7a40xuart_init); +module_exit (lh7a40xuart_exit); + +MODULE_AUTHOR ("Marc Singer"); +MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver"); +MODULE_LICENSE ("GPL"); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 3b7f089002e9..6f61c8fb58a2 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -290,8 +290,11 @@ static void destroy_async (struct dev_state *ps, struct list_head *list) spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); - while ((as = async_getcompleted(ps))) + as = async_getcompleted(ps); + while (as) { free_async(as); + as = async_getcompleted(ps); + } } static void destroy_async_on_interface (struct dev_state *ps, unsigned int ifnum) @@ -968,29 +971,27 @@ static int proc_unlinkurb(struct dev_state *ps, void __user *arg) static int processcompl(struct async *as) { struct urb *urb = as->urb; + struct usbdevfs_urb __user *userurb = as->userurb; unsigned int i; if (as->userbuffer) if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length)) return -EFAULT; - if (put_user(urb->status, - &((struct usbdevfs_urb *)as->userurb)->status)) + if (put_user(urb->status, &userurb->status)) return -EFAULT; - if (put_user(urb->actual_length, - &((struct usbdevfs_urb *)as->userurb)->actual_length)) + if (put_user(urb->actual_length, &userurb->actual_length)) return -EFAULT; - if (put_user(urb->error_count, - &((struct usbdevfs_urb *)as->userurb)->error_count)) + if (put_user(urb->error_count, &userurb->error_count)) return -EFAULT; if (!(usb_pipeisoc(urb->pipe))) return 0; for (i = 0; i < urb->number_of_packets; i++) { if (put_user(urb->iso_frame_desc[i].actual_length, - &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length)) + &userurb->iso_frame_desc[i].actual_length)) return -EFAULT; if (put_user(urb->iso_frame_desc[i].status, - &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status)) + &userurb->iso_frame_desc[i].status)) return -EFAULT; } return 0; diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index aa01713469ff..69b19c22f68f 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2268,9 +2268,17 @@ static int radeonfb_pci_register (struct pci_dev *pdev, /* * Map the BIOS ROM if any and retreive PLL parameters from - * either BIOS or Open Firmware + * the BIOS. We skip that on mobility chips as the real panel + * values we need aren't in the ROM but in the BIOS image in + * memory. This is definitely not the best meacnism though, + * we really need the arch code to tell us which is the "primary" + * video adapter to use the memory image (or better, the arch + * should provide us a copy of the BIOS image to shield us from + * archs who would store that elsewhere and/or could initialize + * more than one adapter during boot). */ - radeon_map_ROM(rinfo, pdev); + if (!rinfo->is_mobility) + radeon_map_ROM(rinfo, pdev); /* * On x86, the primary display on laptop may have it's BIOS @@ -2283,6 +2291,12 @@ static int radeonfb_pci_register (struct pci_dev *pdev, radeon_find_mem_vbios(rinfo); #endif /* __i386__ */ + /* If both above failed, try the BIOS ROM again for mobility + * chips + */ + if (rinfo->bios_seg == NULL && rinfo->is_mobility) + radeon_map_ROM(rinfo, pdev); + /* Get informations about the board's PLL */ radeon_get_pllinfo(rinfo); diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index b14a667dbd81..1bca4cd1f71b 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -328,17 +328,17 @@ static struct sa1100fb_mach_info brutus_info __initdata = { #ifdef CONFIG_SA1100_COLLIE static struct sa1100fb_mach_info collie_info __initdata = { - pixclock: 171521, bpp: 16, - xres: 320, yres: 240, + .pixclock = 171521, .bpp = 16, + .xres = 320, .yres = 240, - hsync_len: 5, vsync_len: 1, - left_margin: 11, upper_margin: 2, - right_margin: 30, lower_margin: 0, + .hsync_len = 5, .vsync_len = 1, + .left_margin = 11, .upper_margin = 2, + .right_margin = 30, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), }; #endif diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 5e66bc917c28..deab8f23ffa1 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2490,7 +2490,8 @@ static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, return 0; } /* End Function devfs_mknod */ -static int devfs_readlink(struct dentry *dentry, char *buffer, int buflen) +static int devfs_readlink(struct dentry *dentry, char __user *buffer, + int buflen) { int err; struct devfs_entry *de; diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 6a3531580946..a7eb88163095 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -30,7 +30,7 @@ #define NCP_PACKET_SIZE_INTERNAL 65536 static int -ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info* arg) +ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info __user *arg) { struct ncp_fs_info info; @@ -58,7 +58,7 @@ ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_in } static int -ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2* arg) +ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2 __user * arg) { struct ncp_fs_info_v2 info2; @@ -90,7 +90,7 @@ ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs * Thanks Petr Vandrovec for idea and many hints. */ static int -ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl* arg) +ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) { struct ncp_nls_ioctl user; struct nls_table *codepage; @@ -148,7 +148,7 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl* arg) } static int -ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl* arg) +ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) { struct ncp_nls_ioctl user; int len; @@ -185,6 +185,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, int result; struct ncp_ioctl_request request; char* bouncebuffer; + void __user *argp = (void __user *)arg; switch (cmd) { case NCP_IOC_NCPREQUEST: @@ -193,8 +194,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, && (current->uid != server->m.mounted_uid)) { return -EACCES; } - if (copy_from_user(&request, (struct ncp_ioctl_request *) arg, - sizeof(request))) + if (copy_from_user(&request, argp, sizeof(request))) return -EFAULT; if ((request.function > 255) @@ -245,10 +245,10 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return ncp_conn_logged_in(inode->i_sb); case NCP_IOC_GET_FS_INFO: - return ncp_get_fs_info(server, inode, (struct ncp_fs_info *)arg); + return ncp_get_fs_info(server, inode, argp); case NCP_IOC_GET_FS_INFO_V2: - return ncp_get_fs_info_v2(server, inode, (struct ncp_fs_info_v2 *)arg); + return ncp_get_fs_info_v2(server, inode, argp); case NCP_IOC_GETMOUNTUID2: { @@ -259,7 +259,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { return -EACCES; } - if (put_user(tmp, (unsigned long*) arg)) + if (put_user(tmp, (unsigned long __user *)argp)) return -EFAULT; return 0; } @@ -292,9 +292,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, sr.namespace = 0; sr.dirEntNum = 0; } - if (copy_to_user((struct ncp_setroot_ioctl*)arg, - &sr, - sizeof(sr))) return -EFAULT; + if (copy_to_user(argp, &sr, sizeof(sr))) + return -EFAULT; return 0; } case NCP_IOC_SETROOT: @@ -308,9 +307,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return -EACCES; } if (server->root_setuped) return -EBUSY; - if (copy_from_user(&sr, - (struct ncp_setroot_ioctl*)arg, - sizeof(sr))) return -EFAULT; + if (copy_from_user(&sr, argp, sizeof(sr))) + return -EFAULT; if (sr.volNumber < 0) { server->m.mounted_vol[0] = 0; vnum = NCP_NUMBER_OF_VOLUMES; @@ -348,13 +346,13 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { return -EACCES; } - if (arg) { + if (argp) { if (server->sign_wanted) { struct ncp_sign_init sign; - if (copy_from_user(&sign, (struct ncp_sign_init *) arg, - sizeof(sign))) return -EFAULT; + if (copy_from_user(&sign, argp, sizeof(sign))) + return -EFAULT; memcpy(server->sign_root,sign.sign_root,8); memcpy(server->sign_last,sign.sign_last,16); server->sign_active = 1; @@ -372,7 +370,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return -EACCES; } - if (put_user(server->sign_wanted, (int*) arg)) + if (put_user(server->sign_wanted, (int __user *)argp)) return -EFAULT; return 0; case NCP_IOC_SET_SIGN_WANTED: @@ -385,7 +383,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return -EACCES; } /* get only low 8 bits... */ - if (get_user(newstate, (unsigned char *) arg)) + if (get_user(newstate, (unsigned char __user *)argp)) return -EFAULT; if (server->sign_active) { /* cannot turn signatures OFF when active */ @@ -409,8 +407,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, struct ncp_lock_ioctl rqdata; int result; - if (copy_from_user(&rqdata, (struct ncp_lock_ioctl*)arg, - sizeof(rqdata))) return -EFAULT; + if (copy_from_user(&rqdata, argp, sizeof(rqdata))) + return -EFAULT; if (rqdata.origin != 0) return -EINVAL; /* check for cmd */ @@ -480,9 +478,8 @@ outrel: struct ncp_objectname_ioctl user; size_t outl; - if (copy_from_user(&user, - (struct ncp_objectname_ioctl*)arg, - sizeof(user))) return -EFAULT; + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; user.auth_type = server->auth.auth_type; outl = user.object_name_len; user.object_name_len = server->auth.object_name_len; @@ -493,9 +490,8 @@ outrel: server->auth.object_name, outl)) return -EFAULT; } - if (copy_to_user((struct ncp_objectname_ioctl*)arg, - &user, - sizeof(user))) return -EFAULT; + if (copy_to_user(argp, &user, sizeof(user))) + return -EFAULT; return 0; } case NCP_IOC_SETOBJECTNAME: @@ -510,9 +506,8 @@ outrel: void* oldprivate; size_t oldprivatelen; - if (copy_from_user(&user, - (struct ncp_objectname_ioctl*)arg, - sizeof(user))) return -EFAULT; + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) return -ENOMEM; if (user.object_name_len) { @@ -550,9 +545,8 @@ outrel: struct ncp_privatedata_ioctl user; size_t outl; - if (copy_from_user(&user, - (struct ncp_privatedata_ioctl*)arg, - sizeof(user))) return -EFAULT; + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; outl = user.len; user.len = server->priv.len; if (outl > user.len) outl = user.len; @@ -561,9 +555,8 @@ outrel: server->priv.data, outl)) return -EFAULT; } - if (copy_to_user((struct ncp_privatedata_ioctl*)arg, - &user, - sizeof(user))) return -EFAULT; + if (copy_to_user(argp, &user, sizeof(user))) + return -EFAULT; return 0; } case NCP_IOC_SETPRIVATEDATA: @@ -576,9 +569,8 @@ outrel: void* old; size_t oldlen; - if (copy_from_user(&user, - (struct ncp_privatedata_ioctl*)arg, - sizeof(user))) return -EFAULT; + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; if (user.len > NCP_PRIVATE_DATA_MAX_LEN) return -ENOMEM; if (user.len) { @@ -603,10 +595,10 @@ outrel: #ifdef CONFIG_NCPFS_NLS case NCP_IOC_SETCHARSETS: - return ncp_set_charsets(server, (struct ncp_nls_ioctl *)arg); + return ncp_set_charsets(server, argp); case NCP_IOC_GETCHARSETS: - return ncp_get_charsets(server, (struct ncp_nls_ioctl *)arg); + return ncp_get_charsets(server, argp); #endif /* CONFIG_NCPFS_NLS */ @@ -617,7 +609,7 @@ outrel: { u_int32_t user; - if (copy_from_user(&user, (u_int32_t*)arg, sizeof(user))) + if (copy_from_user(&user, argp, sizeof(user))) return -EFAULT; /* 20 secs at most... */ if (user > 20000) @@ -630,7 +622,7 @@ outrel: case NCP_IOC_GETDENTRYTTL: { u_int32_t user = (server->dentry_ttl * 1000) / HZ; - if (copy_to_user((u_int32_t*)arg, &user, sizeof(user))) + if (copy_to_user(argp, &user, sizeof(user))) return -EFAULT; return 0; } @@ -646,7 +638,7 @@ outrel: return -EACCES; } SET_UID(uid, server->m.mounted_uid); - if (put_user(uid, (__kernel_uid_t *) arg)) + if (put_user(uid, (__kernel_uid_t __user *)argp)) return -EFAULT; return 0; } diff --git a/fs/proc/base.c b/fs/proc/base.c index 5d62232721e6..9e3a70ea23f9 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1463,7 +1463,8 @@ static struct inode_operations proc_tid_attr_inode_operations = { /* * /proc/self: */ -static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen) +static int proc_self_readlink(struct dentry *dentry, char __user *buffer, + int buflen) { char tmp[30]; sprintf(tmp, "%d", current->tgid); @@ -1747,7 +1748,9 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) ino_t ino = fake_ino(tgid,PROC_TGID_INO); unsigned long j = PROC_NUMBUF; - do buf[--j] = '0' + (tgid % 10); while (tgid/=10); + do + buf[--j] = '0' + (tgid % 10); + while ((tgid /= 10) != 0); if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) { filp->f_version = tgid; @@ -1799,7 +1802,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi do buf[--j] = '0' + (tid % 10); - while (tid /= 10); + while ((tid /= 10) != 0); if (filldir(dirent, buf+j, PROC_NUMBUF-j, pos, ino, DT_DIR) < 0) break; diff --git a/fs/quota.c b/fs/quota.c index 680dd072a8c6..cf2c31ea8df0 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -150,7 +150,7 @@ void sync_dquots(struct super_block *sb, int type) } /* Copy parameters and call proper function */ -static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr) +static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr) { int ret; @@ -264,7 +264,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, cadd * calls. Maybe we need to add the process quotas etc. in the future, * but we probably should use rlimits for that. */ -asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, caddr_t addr) +asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr) { uint cmds, type; struct super_block *sb = NULL; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index ac5c0b962ba9..d0030a4b151a 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -46,8 +46,13 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) struct inode * inode = NULL; if (dentry) { if (!dentry->d_inode) { - if ((inode = sysfs_new_inode(mode))) + if ((inode = sysfs_new_inode(mode))) { + if (dentry->d_parent && dentry->d_parent->d_inode) { + struct inode *p_inode = dentry->d_parent->d_inode; + p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; + } goto Proceed; + } else error = -ENOMEM; } else diff --git a/include/asm-arm/arch-adifcc/adi_evb.h b/include/asm-arm/arch-adifcc/adi_evb.h deleted file mode 100644 index f4b74c6fcf9a..000000000000 --- a/include/asm-arm/arch-adifcc/adi_evb.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm/arch-80200fcc/adi_evb.h - * - * ADI 80200FCC evaluation board definitions - * - * Author: Deepak Saxena <dsaxena@mvista.com> - * - * Copyright (C) 2001 MontaVista Software Inc. - * - * 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. - */ - -#define ADI_EVB__RAMBASE 0xa0000000 -#define ADI_EVB__UART 0x00400000 /* UART */ -#define ADI_EVB_7SEG_1 0x00500000 /* 7-Segment */ - diff --git a/include/asm-arm/arch-adifcc/dma.h b/include/asm-arm/arch-adifcc/dma.h deleted file mode 100644 index 19aa1dbc3be7..000000000000 --- a/include/asm-arm/arch-adifcc/dma.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * linux/include/asm-arm/arch-80200fcc/dma.h - * - * Copyright (C) 2001 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#define MAX_DMA_ADDRESS 0xffffffff - -/* No DMA */ -#define MAX_DMA_CHANNELS 0 - -#endif /* _ASM_ARCH_DMA_H */ diff --git a/include/asm-arm/arch-adifcc/hardware.h b/include/asm-arm/arch-adifcc/hardware.h deleted file mode 100644 index 9eeb3cb507da..000000000000 --- a/include/asm-arm/arch-adifcc/hardware.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/hardware.h - * - * Hardware definitions for ADI based systems - * - * Author: Deepak Saxena <dsaxena@mvista.com> - * - * Copyright (C) 2000-2001 MontaVista Software Inc. - * - * 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. - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -#include <linux/config.h> - -#define PCIO_BASE 0 - -#if defined(CONFIG_ARCH_ADI_EVB) -#include "adi_evb.h" -#endif - -#endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/include/asm-arm/arch-adifcc/io.h b/include/asm-arm/arch-adifcc/io.h deleted file mode 100644 index bdcaec08bddf..000000000000 --- a/include/asm-arm/arch-adifcc/io.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/io.h - * - * Author: Deepak Saxena <dsaxena@mvista.com> - * - * Copyright (C) 2001 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -#define IO_SPACE_LIMIT 0xffffffff - -#define __io(a) (PCIO_BASE + (a)) -#define __mem_pci(a) ((unsigned long)(a)) -#define __mem_isa(a) ((unsigned long)(a)) - -#endif diff --git a/include/asm-arm/arch-adifcc/irqs.h b/include/asm-arm/arch-adifcc/irqs.h deleted file mode 100644 index b559ca79ef80..000000000000 --- a/include/asm-arm/arch-adifcc/irqs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/include/asm-arm/arch-80200fcc/irqs.h - * - * Author: Deepak Saxena <dsaxena@mvista.com> - * Copyright: (C) 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define IRQ_XS80200_BCU 0 /* Bus Control Unit */ -#define IRQ_XS80200_PMU 1 /* Performance Monitoring Unit */ -#define IRQ_XS80200_EXTIRQ 2 /* external IRQ signal */ -#define IRQ_XS80200_EXTFIQ 3 /* external IRQ signal */ - -#define NR_XS80200_IRQS 4 -#define NR_IRQS NR_XS80200_IRQS - -#define IRQ_XSCALE_PMU IRQ_XS80200_PMU diff --git a/include/asm-arm/arch-adifcc/memory.h b/include/asm-arm/arch-adifcc/memory.h deleted file mode 100644 index b76187d8d42b..000000000000 --- a/include/asm-arm/arch-adifcc/memory.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/memory.h - * - * Copyright (c) 2001 MontaVista Software, Inc. - */ - -#ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H - -/* - * Physical DRAM offset. - */ -#define PHYS_OFFSET (0xC0000000UL) - -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - * - * These are dummies for now. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -#endif diff --git a/include/asm-arm/arch-adifcc/param.h b/include/asm-arm/arch-adifcc/param.h deleted file mode 100644 index b1a410eff447..000000000000 --- a/include/asm-arm/arch-adifcc/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/param.h - */ diff --git a/include/asm-arm/arch-adifcc/serial.h b/include/asm-arm/arch-adifcc/serial.h deleted file mode 100644 index ce4e87699c91..000000000000 --- a/include/asm-arm/arch-adifcc/serial.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * include/asm-arm/arch-adifcc/serial.h - * - * Author: Deepak Saxena <dsaxena@mvista.com> - * - * Copyright (c) 2001 MontaVista Software, Inc. - */ -#include <linux/config.h> - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ -#define BASE_BAUD ( 1852000 / 16 ) - -/* Standard COM flags */ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - -#ifdef CONFIG_ARCH_ADI_EVB - -/* - * One serial port, int goes to FIQ, so we run in polled mode - */ -#define STD_SERIAL_PORT_DEFNS \ - /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0xff400000, 0, STD_COM_FLAGS } /* ttyS0 */ - -#define EXTRA_SERIAL_PORT_DEFNS - -#endif - diff --git a/include/asm-arm/arch-adifcc/system.h b/include/asm-arm/arch-adifcc/system.h deleted file mode 100644 index 4bffbdc294a0..000000000000 --- a/include/asm-arm/arch-adifcc/system.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/system.h - * - * Copyright (C) 2001 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -static inline void arch_idle(void) -{ -#if 0 - cpu_do_idle(); -#endif -} - - -static inline void arch_reset(char mode) -{ - if ( 1 && mode == 's') { - /* Jump into ROM at address 0 */ - cpu_reset(0); - } else { - /* Use on-chip reset capability */ - } -} - diff --git a/include/asm-arm/arch-adifcc/time.h b/include/asm-arm/arch-adifcc/time.h deleted file mode 100644 index 2237ef006e71..000000000000 --- a/include/asm-arm/arch-adifcc/time.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/time.h - * - */ - -/* - * No on board timer, implementation @ arch/arm/kernel/xscale-time.c - */ - diff --git a/include/asm-arm/arch-adifcc/timex.h b/include/asm-arm/arch-adifcc/timex.h deleted file mode 100644 index d994c8abecd5..000000000000 --- a/include/asm-arm/arch-adifcc/timex.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/timex.h - * - * XScale architecture timex specifications - */ - -/* This is for a timer based on the XS80200's PMU counter */ - -#define CLOCK_TICK_RATE 600000000 /* Underlying HZ */ - diff --git a/include/asm-arm/arch-adifcc/uncompress.h b/include/asm-arm/arch-adifcc/uncompress.h deleted file mode 100644 index 792b4e17aa86..000000000000 --- a/include/asm-arm/arch-adifcc/uncompress.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/uncompress.h - * - * Author: Deepak Saxena <dsaxena@mvista.com> - * - * Copyright (c) 2001 MontaVista Software, Inc. - * - */ - -#define UART_BASE ((volatile unsigned char *)0x00400000) - -static __inline__ void putc(char c) -{ - while ((UART_BASE[5] & 0x60) != 0x60); - UART_BASE[0] = c; -} - -/* - * This does not append a newline - */ -static void puts(const char *s) -{ - while (*s) { - putc(*s); - if (*s == '\n') - putc('\r'); - s++; - } -} - -/* - * nothing to do - */ -#define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-adifcc/vmalloc.h b/include/asm-arm/arch-adifcc/vmalloc.h deleted file mode 100644 index d45b27e1ad0e..000000000000 --- a/include/asm-arm/arch-adifcc/vmalloc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * linux/include/asm-arm/arch-adifcc/vmalloc.h - */ - -/* - * Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_END (0xe8000000) diff --git a/include/asm-arm/arch-cl7500/time.h b/include/asm-arm/arch-cl7500/time.h deleted file mode 100644 index e5e5be510265..000000000000 --- a/include/asm-arm/arch-cl7500/time.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * linux/include/asm-arm/arch-cl7500/time.h - * - * Copyright (c) 1996-2000 Russell King. - * - * Changelog: - * 24-Sep-1996 RMK Created - * 10-Oct-1996 RMK Brought up to date with arch-sa110eval - * 04-Dec-1997 RMK Updated for new arch/arm/time.c - */ - -extern void ioctime_init(void); - -static irqreturn_t -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - do_timer(regs); - do_set_rtc(); - do_profile(regs); - - { - /* Twinkle the lights. */ - static int count, state = 0xff00; - if (count-- == 0) { - state ^= 0x100; - count = 25; - *((volatile unsigned int *)LED_ADDRESS) = state; - } - } - return IRQ_HANDLED; -} - -/* - * Set up timer interrupt. - */ -void __init time_init(void) -{ - ioctime_init(); - - timer_irq.handler = timer_interrupt; - - setup_irq(IRQ_TIMER, &timer_irq); -} diff --git a/include/asm-arm/arch-epxa10db/time.h b/include/asm-arm/arch-epxa10db/time.h deleted file mode 100644 index 749770b83e9a..000000000000 --- a/include/asm-arm/arch-epxa10db/time.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * linux/include/asm-arm/arch-epxa10db/time.h - * - * Copyright (C) 2001 Altera Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <asm/system.h> -#include <asm/leds.h> -#include <asm/arch/hardware.h> -#define TIMER00_TYPE (volatile unsigned int*) -#include <asm/arch/timer00.h> - - -/* - * IRQ handler for the timer - */ -static irqreturn_t -excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - - // ...clear the interrupt - *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK; - - do_leds(); - do_timer(regs); - do_profile(regs); - - return IRQ_HANDLED; -} - -/* - * Set up timer interrupt, and return the current time in seconds. - */ -void __init time_init(void) -{ - timer_irq.handler = excalibur_timer_interrupt; - - /* - * Make irqs happen for the system timer - */ - setup_irq(IRQ_TIMER0, &timer_irq); - - /* Start the timer */ - *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200); - *TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1; - *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK; -} diff --git a/include/asm-arm/arch-integrator/platform.h b/include/asm-arm/arch-integrator/platform.h index 6b67e41669f4..09ec7902f4bf 100644 --- a/include/asm-arm/arch-integrator/platform.h +++ b/include/asm-arm/arch-integrator/platform.h @@ -457,6 +457,10 @@ #define mSEC_25 (mSEC_1 * 25) #define SEC_1 (mSEC_1 * 1000) +#ifndef __ASSEMBLY__ +extern void integrator_time_init(unsigned long, unsigned int); +#endif + #define INTEGRATOR_CSR_BASE 0x10000000 #define INTEGRATOR_CSR_SIZE 0x10000000 diff --git a/include/asm-arm/arch-iop3xx/time.h b/include/asm-arm/arch-iop3xx/time.h deleted file mode 100644 index b58ac84f954e..000000000000 --- a/include/asm-arm/arch-iop3xx/time.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * linux/include/asm-arm/arch-iop80310/time.h - * - * Author: Nicolas Pitre - * Copyright: (C) 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h index 52c1c445c536..b8ea57968d4a 100644 --- a/include/asm-arm/arch-ixp4xx/platform.h +++ b/include/asm-arm/arch-ixp4xx/platform.h @@ -58,6 +58,7 @@ struct ixp4xx_i2c_pins { */ extern void ixp4xx_map_io(void); extern void ixp4xx_init_irq(void); +extern void ixp4xx_init_time(void); extern void ixp4xx_pci_preinit(void); struct pci_sys_data; extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); diff --git a/include/asm-arm/arch-ixp4xx/time.h b/include/asm-arm/arch-ixp4xx/time.h deleted file mode 100644 index e79f4acbe7b3..000000000000 --- a/include/asm-arm/arch-ixp4xx/time.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * linux/include/asm-arm/arch-ixp4xx/time.h - * - * We implement timer code in arch/arm/mach-ixp4xx/time.c - * - */ - diff --git a/include/asm-arm/arch-rpc/time.h b/include/asm-arm/arch-rpc/time.h deleted file mode 100644 index 1df6a12cd0e3..000000000000 --- a/include/asm-arm/arch-rpc/time.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/include/asm-arm/arch-rpc/time.h - * - * Copyright (C) 1996-2000 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Changelog: - * 24-Sep-1996 RMK Created - * 10-Oct-1996 RMK Brought up to date with arch-sa110eval - * 04-Dec-1997 RMK Updated for new arch/arm/time.c - */ -extern void ioctime_init(void); - -static irqreturn_t -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - do_timer(regs); - do_set_rtc(); - do_profile(regs); - - return IRQ_HANDLED; -} - -/* - * Set up timer interrupt. - */ -void __init time_init(void) -{ - ioctime_init(); - - timer_irq.handler = timer_interrupt; - - setup_irq(IRQ_TIMER, &timer_irq); -} diff --git a/include/asm-arm/arch-shark/time.h b/include/asm-arm/arch-shark/time.h deleted file mode 100644 index 66e45254a628..000000000000 --- a/include/asm-arm/arch-shark/time.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * linux/include/asm-arm/arch-shark/time.h - * - * by Alexander Schulz - * - * derived from include/asm-arm/arch-ebsa110/time.h - * Copyright (c) 1996,1997,1998 Russell King. - */ - -#include <asm/leds.h> -#include <asm/param.h> - -#define IRQ_TIMER 0 -#define HZ_TIME ((1193180 + HZ/2) / HZ) - -static irqreturn_t -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - do_leds(); - do_timer(regs); - do_profile(regs); - - return IRQ_HANDLED; -} - -/* - * Set up timer interrupt, and return the current time in seconds. - */ -void __init time_init(void) -{ - unsigned long flags; - - outb(0x34, 0x43); /* binary, mode 0, LSB/MSB, Ch 0 */ - outb(HZ_TIME & 0xff, 0x40); /* LSB of count */ - outb(HZ_TIME >> 8, 0x40); - - timer_irq.handler = timer_interrupt; - setup_irq(IRQ_TIMER, &timer_irq); -} diff --git a/include/asm-arm/arch-versatile/time.h b/include/asm-arm/arch-versatile/time.h deleted file mode 100644 index 7d97d9565a4b..000000000000 --- a/include/asm-arm/arch-versatile/time.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * linux/include/asm-arm/arch-versatile/time.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <asm/system.h> -#include <asm/leds.h> - -/* - * Where is the timer (VA)? - */ -#define TIMER0_VA_BASE IO_ADDRESS(VERSATILE_TIMER0_1_BASE) -#define TIMER1_VA_BASE (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20) -#define TIMER2_VA_BASE IO_ADDRESS(VERSATILE_TIMER2_3_BASE) -#define TIMER3_VA_BASE (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20) -#define VA_IC_BASE IO_ADDRESS(VERSATILE_VIC_BASE) - -/* - * How long is the timer interval? - */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 8) /* Divide by 256 */ -#define TIMER_CTRL 0x88 /* Enable, Clock / 256 */ -#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) -#elif TIMER_INTERVAL >= 0x10000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ -#define TIMER_CTRL 0x84 /* Enable, Clock / 16 */ -#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) -#else -#define TIMER_RELOAD (TIMER_INTERVAL) -#define TIMER_CTRL 0x80 /* Enable */ -#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) -#endif - -#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ - -/* - * What does it look like? - */ -typedef struct TimerStruct { - unsigned long TimerLoad; - unsigned long TimerValue; - unsigned long TimerControl; - unsigned long TimerClear; -} TimerStruct_t; - -extern unsigned long (*gettimeoffset)(void); - -/* - * Returns number of ms since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - */ -static unsigned long versatile_gettimeoffset(void) -{ - volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE; - unsigned long ticks1, ticks2, status; - - /* - * Get the current number of ticks. Note that there is a race - * condition between us reading the timer and checking for - * an interrupt. We get around this by ensuring that the - * counter has not reloaded between our two reads. - */ - ticks2 = timer0->TimerValue & 0xffff; - do { - ticks1 = ticks2; - status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); - ticks2 = timer0->TimerValue & 0xffff; - } while (ticks2 > ticks1); - - /* - * Number of ticks since last interrupt. - */ - ticks1 = TIMER_RELOAD - ticks2; - - /* - * Interrupt pending? If so, we've reloaded once already. - * - * FIXME: Need to check this is effectively timer 0 that expires - */ - if (status & IRQMASK_TIMERINT0_1) - ticks1 += TIMER_RELOAD; - - /* - * Convert the ticks to usecs - */ - return TICKS2USECS(ticks1); -} - -/* - * IRQ handler for the timer - */ -static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; - - // ...clear the interrupt - timer0->TimerClear = 1; - - do_leds(); - do_timer(regs); - do_profile(regs); - - return IRQ_HANDLED; -} - -/* - * Set up timer interrupt, and return the current time in seconds. - */ -void __init time_init(void) -{ - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; - volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; - volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE; - volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE; - - /* - * set clock frequency: - * VERSATILE_REFCLK is 32KHz - * VERSATILE_TIMCLK is 1MHz - */ - *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= - ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | - (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel)); - - timer_irq.handler = versatile_timer_interrupt; - - /* - * Initialise to a known state (all timers off) - */ - timer0->TimerControl = 0; - timer1->TimerControl = 0; - timer2->TimerControl = 0; - timer3->TimerControl = 0; - - timer0->TimerLoad = TIMER_RELOAD; - timer0->TimerValue = TIMER_RELOAD; - timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE; /* periodic + IE */ - - /* - * Make irqs happen for the system timer - */ - setup_irq(IRQ_TIMERINT0_1, &timer_irq); - gettimeoffset = versatile_gettimeoffset; -} diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h index daa0f4e0abbf..f82f595c75af 100644 --- a/include/asm-arm/checksum.h +++ b/include/asm-arm/checksum.h @@ -9,6 +9,8 @@ #ifndef __ASM_ARM_CHECKSUM_H #define __ASM_ARM_CHECKSUM_H +#include <linux/in6.h> + /* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) diff --git a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h index 00f936197ad9..ff48022e4720 100644 --- a/include/asm-arm/cpu-multi32.h +++ b/include/asm-arm/cpu-multi32.h @@ -7,9 +7,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifndef __ASSEMBLY__ - -#include <asm/memory.h> #include <asm/page.h> struct mm_struct; @@ -64,16 +61,4 @@ extern struct processor { #define cpu_do_idle() processor._do_idle() #define cpu_dcache_clean_area(addr,sz) processor.dcache_clean_area(addr,sz) #define cpu_set_pte(ptep, pte) processor.set_pte(ptep, pte) - -#define cpu_switch_mm(pgd,mm) processor.switch_mm(__virt_to_phys((unsigned long)(pgd)),mm) - -#define cpu_get_pgd() \ - ({ \ - unsigned long pg; \ - __asm__("mrc p15, 0, %0, c2, c0, 0" \ - : "=r" (pg) : : "cc"); \ - pg &= ~0x3fff; \ - (pgd_t *)phys_to_virt(pg); \ - }) - -#endif +#define cpu_do_switch_mm(pgd,mm) processor.switch_mm(pgd,mm) diff --git a/include/asm-arm/cpu-single.h b/include/asm-arm/cpu-single.h index cc213ad7167f..b5ec5d54665d 100644 --- a/include/asm-arm/cpu-single.h +++ b/include/asm-arm/cpu-single.h @@ -27,12 +27,9 @@ #define cpu_reset __cpu_fn(CPU_NAME,_reset) #define cpu_do_idle __cpu_fn(CPU_NAME,_do_idle) #define cpu_dcache_clean_area __cpu_fn(CPU_NAME,_dcache_clean_area) -#define cpu__switch_mm __cpu_fn(CPU_NAME,_switch_mm) +#define cpu_do_switch_mm __cpu_fn(CPU_NAME,_switch_mm) #define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte) -#ifndef __ASSEMBLY__ - -#include <asm/memory.h> #include <asm/page.h> struct mm_struct; @@ -42,20 +39,6 @@ extern void cpu_proc_init(void); extern void cpu_proc_fin(void); extern int cpu_do_idle(void); extern void cpu_dcache_clean_area(void *, int); -extern void cpu__switch_mm(unsigned long pgd_phys, struct mm_struct *mm); +extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); extern void cpu_set_pte(pte_t *ptep, pte_t pte); - extern volatile void cpu_reset(unsigned long addr); - -#define cpu_switch_mm(pgd,mm) cpu__switch_mm(__virt_to_phys((unsigned long)(pgd)),mm) - -#define cpu_get_pgd() \ - ({ \ - unsigned long pg; \ - __asm__("mrc p15, 0, %0, c2, c0, 0" \ - : "=r" (pg) : : "cc"); \ - pg &= ~0x3fff; \ - (pgd_t *)phys_to_virt(pg); \ - }) - -#endif diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h index d751faf725de..37ae74796331 100644 --- a/include/asm-arm/mach/arch.h +++ b/include/asm-arm/mach/arch.h @@ -45,6 +45,7 @@ struct machine_desc { struct meminfo *); void (*map_io)(void);/* IO mapping function */ void (*init_irq)(void); + void (*init_time)(void); void (*init_machine)(void); }; @@ -87,6 +88,9 @@ const struct machine_desc __mach_desc_##_type \ #define INITIRQ(_func) \ .init_irq = _func, +#define INITTIME(_func) \ + .init_time = _func, + #define INIT_MACHINE(_func) \ .init_machine = _func, diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h new file mode 100644 index 000000000000..edb6fcc6a200 --- /dev/null +++ b/include/asm-arm/mach/time.h @@ -0,0 +1,20 @@ +/* + * linux/include/asm-arm/mach/time.h + * + * Copyright (C) 2004 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ASM_ARM_MACH_TIME_H +#define __ASM_ARM_MACH_TIME_H + +extern void (*init_arch_time)(void); + +extern int (*set_rtc)(void); +extern unsigned long(*gettimeoffset)(void); + +void timer_tick(struct pt_regs *); + +#endif diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h index 9599c6e2f55a..7bef2bf6be51 100644 --- a/include/asm-arm/proc-fns.h +++ b/include/asm-arm/proc-fns.h @@ -148,11 +148,27 @@ # endif #endif +#ifndef __ASSEMBLY__ + #ifndef MULTI_CPU #include "asm/cpu-single.h" #else #include "asm/cpu-multi32.h" #endif +#include <asm/memory.h> + +#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) + +#define cpu_get_pgd() \ + ({ \ + unsigned long pg; \ + __asm__("mrc p15, 0, %0, c2, c0, 0" \ + : "=r" (pg) : : "cc"); \ + pg &= ~0x3fff; \ + (pgd_t *)phys_to_virt(pg); \ + }) + +#endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* __ASM_PROCFNS_H */ diff --git a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h index 11065e368382..ee15e9c59aa2 100644 --- a/include/asm-ppc/pmac_feature.h +++ b/include/asm-ppc/pmac_feature.h @@ -273,6 +273,12 @@ static inline long pmac_call_feature(int selector, struct device_node* node, */ #define PMAC_FTR_ENABLE_MPIC PMAC_FTR_DEF(19) +/* PMAC_FTR_AACK_DELAY_ENABLE (NULL, int enable, 0) + * + * Enable/disable the AACK delay on the northbridge for systems using DFS + */ +#define PMAC_FTR_AACK_DELAY_ENABLE PMAC_FTR_DEF(20) + /* Don't use those directly, they are for the sake of pmac_setup.c */ extern long pmac_do_feature_call(unsigned int selector, ...); diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index fe7a94383a1d..63fc68e784c5 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -197,6 +197,8 @@ extern inline void prefetchw(const void *x) #define spin_lock_prefetch(x) prefetchw(x) +extern int emulate_altivec(struct pt_regs *regs); + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_PPC_PROCESSOR_H */ diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h index f02ec3cf65ec..15c93af4079a 100644 --- a/include/asm-ppc/reg.h +++ b/include/asm-ppc/reg.h @@ -174,6 +174,7 @@ #define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */ #define HID1_EMCP (1<<31) /* 7450 Machine Check Pin Enable */ +#define HID1_DFS (1<<22) /* 7447A Dynamic Frequency Scaling */ #define HID1_PC0 (1<<16) /* 7450 PLL_CFG[0] */ #define HID1_PC1 (1<<15) /* 7450 PLL_CFG[1] */ #define HID1_PC2 (1<<14) /* 7450 PLL_CFG[2] */ diff --git a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h index eeff122f365b..2cf025936edf 100644 --- a/include/asm-ppc/uninorth.h +++ b/include/asm-ppc/uninorth.h @@ -142,6 +142,12 @@ */ #define UNI_N_HWINIT_STATE_CPU1_FLAG 0x10000000 +/* This register controls AACK delay, which is set when 2004 iBook/PowerBook + * is in low speed mode. + */ +#define UNI_N_AACK_DELAY 0x0100 +#define UNI_N_AACK_DELAY_ENABLE 0x00000001 + /* Uninorth 1.5 rev. has additional perf. monitor registers at 0xf00-0xf50 */ diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index 67ac484a14cd..06ecd1bb285d 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -116,6 +116,7 @@ extern void enable_kernel_fp(void); extern void giveup_altivec(struct task_struct *); extern void disable_kernel_altivec(void); extern void enable_kernel_altivec(void); +extern int emulate_altivec(struct pt_regs *); extern void cvt_fd(float *from, double *to, unsigned long *fpscr); extern void cvt_df(double *from, float *to, unsigned long *fpscr); diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h index bdaba5ccc11e..bfac1afa9983 100644 --- a/include/asm-sparc64/bug.h +++ b/include/asm-sparc64/bug.h @@ -3,6 +3,8 @@ #ifndef _SPARC64_BUG_H #define _SPARC64_BUG_H +#include <linux/compiler.h> + #ifdef CONFIG_DEBUG_BUGVERBOSE extern void do_BUG(const char *file, int line); #define BUG() do { \ diff --git a/include/linux/device.h b/include/linux/device.h index 2b8b3d636889..3f6e14c099e2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -54,6 +54,9 @@ struct bus_type { struct kset drivers; struct kset devices; + struct bus_attribute * bus_attrs; + struct device_attribute * dev_attrs; + int (*match)(struct device * dev, struct device_driver * drv); struct device * (*add) (struct device * parent, char * bus_id); int (*hotplug) (struct device *dev, char **envp, @@ -90,11 +93,7 @@ struct bus_attribute { }; #define BUS_ATTR(_name,_mode,_show,_store) \ -struct bus_attribute bus_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _show, \ - .store = _store, \ -}; +struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int bus_create_file(struct bus_type *, struct bus_attribute *); extern void bus_remove_file(struct bus_type *, struct bus_attribute *); @@ -131,11 +130,7 @@ struct driver_attribute { }; #define DRIVER_ATTR(_name,_mode,_show,_store) \ -struct driver_attribute driver_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _show, \ - .store = _store, \ -}; +struct driver_attribute driver_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int driver_create_file(struct device_driver *, struct driver_attribute *); extern void driver_remove_file(struct device_driver *, struct driver_attribute *); @@ -151,6 +146,9 @@ struct class { struct list_head children; struct list_head interfaces; + struct class_attribute * class_attrs; + struct class_device_attribute * class_dev_attrs; + int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size); @@ -172,11 +170,7 @@ struct class_attribute { }; #define CLASS_ATTR(_name,_mode,_show,_store) \ -struct class_attribute class_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _show, \ - .store = _store, \ -}; +struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int class_create_file(struct class *, const struct class_attribute *); extern void class_remove_file(struct class *, const struct class_attribute *); @@ -224,11 +218,8 @@ struct class_device_attribute { }; #define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \ -struct class_device_attribute class_device_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _show, \ - .store = _store, \ -}; +struct class_device_attribute class_device_attr_##_name = \ + __ATTR(_name,_mode,_show,_store) extern int class_device_create_file(struct class_device *, const struct class_device_attribute *); @@ -342,11 +333,7 @@ struct device_attribute { }; #define DEVICE_ATTR(_name,_mode,_show,_store) \ -struct device_attribute dev_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _show, \ - .store = _store, \ -}; +struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int device_create_file(struct device *device, struct device_attribute * entry); @@ -390,6 +377,10 @@ extern void platform_device_unregister(struct platform_device *); extern struct bus_type platform_bus_type; extern struct device platform_bus; +extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int); +extern int platform_get_irq(struct platform_device *, unsigned int); +extern int platform_add_devices(struct platform_device **, int); + /* drivers/base/power.c */ extern void device_shutdown(void); diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 591e7ad68d30..520fe7220cd3 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -101,6 +101,14 @@ #define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */ #define I2C_DRIVERID_ADV7170 54 /* video encoder */ #define I2C_DRIVERID_RADEON 55 /* I2C bus on Radeon boards */ +#define I2C_DRIVERID_MAX1617 56 /* temp sensor */ +#define I2C_DRIVERID_SAA7191 57 /* video encoder */ +#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ +#define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */ +#define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */ +#define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */ +#define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */ +#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ @@ -264,6 +272,10 @@ #define I2C_HW_SMBUS_SCX200 0x0b #define I2C_HW_SMBUS_NFORCE2 0x0c #define I2C_HW_SMBUS_W9968CF 0x0d +#define I2C_HW_SMBUS_OV511 0x0e /* OV511(+) USB 1.1 webcam ICs */ +#define I2C_HW_SMBUS_OV518 0x0f /* OV518(+) USB 1.1 webcam ICs */ +#define I2C_HW_SMBUS_OV519 0x10 /* OV519 USB 1.1 webcam IC */ +#define I2C_HW_SMBUS_OVFX2 0x11 /* Cypress/OmniVision FX2 webcam */ /* --- ISA pseudo-adapter */ #define I2C_HW_ISA 0x00 diff --git a/include/linux/if.h b/include/linux/if.h index 296a6c21ec71..110282dbd3e0 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -108,15 +108,15 @@ struct if_settings unsigned int size; /* Size of the data allocated by the caller */ union { /* {atm/eth/dsl}_settings anyone ? */ - raw_hdlc_proto *raw_hdlc; - cisco_proto *cisco; - fr_proto *fr; - fr_proto_pvc *fr_pvc; - fr_proto_pvc_info *fr_pvc_info; + raw_hdlc_proto __user *raw_hdlc; + cisco_proto __user *cisco; + fr_proto __user *fr; + fr_proto_pvc __user *fr_pvc; + fr_proto_pvc_info __user *fr_pvc_info; /* interface settings */ - sync_serial_settings *sync; - te1_settings *te1; + sync_serial_settings __user *sync; + te1_settings __user *te1; } ifs_ifsu; }; diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h index 0cc5f030dace..26b00a76e135 100644 --- a/include/linux/isdn_ppp.h +++ b/include/linux/isdn_ppp.h @@ -233,8 +233,9 @@ struct ippp_struct { struct slcompress *slcomp; #endif #ifdef CONFIG_IPPP_FILTER - struct sock_fprog pass_filter; /* filter for packets to pass */ - struct sock_fprog active_filter; /* filter for pkts to reset idle */ + struct sock_filter *pass_filter; /* filter for packets to pass */ + struct sock_filter *active_filter; /* filter for pkts to reset idle */ + unsigned pass_len, active_len; #endif unsigned long debug; struct isdn_ppp_compressor *compressor,*decompressor; diff --git a/include/linux/libata.h b/include/linux/libata.h index 18c90a0c1cfd..a40286d08e23 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -91,6 +91,7 @@ enum { ATA_DFLAG_MASTER = (1 << 2), /* is device 0? */ ATA_DFLAG_WCACHE = (1 << 3), /* has write cache we can * (hopefully) flush? */ + ATA_DFLAG_LOCK_SECTORS = (1 << 4), /* don't adjust max_sectors */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -133,24 +134,10 @@ enum { BUS_IDENTIFY = 8, BUS_PACKET = 9, - /* thread states */ - THR_UNKNOWN = 0, - THR_PORT_RESET = (THR_UNKNOWN + 1), - THR_AWAIT_DEATH = (THR_PORT_RESET + 1), - THR_PROBE_FAILED = (THR_AWAIT_DEATH + 1), - THR_IDLE = (THR_PROBE_FAILED + 1), - THR_PROBE_SUCCESS = (THR_IDLE + 1), - THR_PROBE_START = (THR_PROBE_SUCCESS + 1), - /* SATA port states */ PORT_UNKNOWN = 0, PORT_ENABLED = 1, PORT_DISABLED = 2, - - /* ata_qc_cb_t flags - note uses above ATA_QCFLAG_xxx namespace, - * but not numberspace - */ - ATA_QCFLAG_TIMEOUT = (1 << 0), }; enum pio_task_states { @@ -294,18 +281,12 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; - struct semaphore probe_sem; - - unsigned int thr_state; - struct work_struct packet_task; struct work_struct pio_task; unsigned int pio_task_state; unsigned long pio_task_timeout; - struct work_struct probe_task; - void *private_data; }; @@ -330,7 +311,7 @@ struct ata_port_operations { void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc); - void (*fill_sg) (struct ata_queued_cmd *qc); + void (*qc_prep) (struct ata_queued_cmd *qc); void (*eng_timeout) (struct ata_port *ap); irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); @@ -390,7 +371,7 @@ extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -extern void ata_fill_sg(struct ata_queued_cmd *qc); +extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc); @@ -556,4 +537,44 @@ static inline unsigned int sata_dev_present(struct ata_port *ap) return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; } +static inline void ata_bmdma_stop(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + + /* clear start/stop bit */ + writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, + mmio + ATA_DMA_CMD); + } else { + /* clear start/stop bit */ + outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + } + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_altstatus(ap); /* dummy read */ +} + +static inline void ata_bmdma_ack_irq(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } +} + +static inline u8 ata_bmdma_status(struct ata_port *ap) +{ + u8 host_stat; + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + host_stat = readb(mmio + ATA_DMA_STATUS); + } else + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + return host_stat; +} + #endif /* __LINUX_LIBATA_H__ */ diff --git a/include/linux/module.h b/include/linux/module.h index 2709330e8684..2ad187c3bda1 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -225,6 +225,22 @@ struct module_kobject struct module_attribute attr[0]; }; +/* Similar stuff for section attributes. */ +#define MODULE_SECT_NAME_LEN 32 +struct module_sect_attr +{ + struct attribute attr; + char name[MODULE_SECT_NAME_LEN]; + unsigned long address; +}; + +struct module_sections +{ + struct kobject kobj; + struct module_sect_attr attrs[0]; +}; + + struct module { enum module_state state; @@ -298,6 +314,9 @@ struct module Elf_Sym *symtab; unsigned long num_symtab; char *strtab; + + /* Section attributes */ + struct module_sections *sect_attrs; #endif /* Per-cpu data. */ diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index 9e2f1923ce5c..d9ab889ed7d0 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h @@ -24,7 +24,7 @@ struct ncp_ioctl_request { unsigned int function; unsigned int size; - char *data; + char __user *data; }; struct ncp_fs_info { @@ -88,13 +88,13 @@ struct ncp_objectname_ioctl #define NCP_AUTH_NDS 0x32 int auth_type; size_t object_name_len; - void* object_name; /* an userspace data, in most cases user name */ + void __user * object_name; /* an userspace data, in most cases user name */ }; struct ncp_privatedata_ioctl { size_t len; - void* data; /* ~1000 for NDS */ + void __user * data; /* ~1000 for NDS */ }; /* NLS charsets by ioctl */ diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 26d7f3a11fd7..1974f162f5a0 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -103,7 +103,7 @@ union ip_conntrack_nat_help { #include <linux/types.h> #include <linux/skbuff.h> -#ifdef CONFIG_NF_DEBUG +#ifdef CONFIG_NETFILTER_DEBUG #define IP_NF_ASSERT(x) \ do { \ if (!(x)) \ diff --git a/include/linux/netfilter_ipv4/ipt_addrtype.h b/include/linux/netfilter_ipv4/ipt_addrtype.h new file mode 100644 index 000000000000..166ed01a8122 --- /dev/null +++ b/include/linux/netfilter_ipv4/ipt_addrtype.h @@ -0,0 +1,11 @@ +#ifndef _IPT_ADDRTYPE_H +#define _IPT_ADDRTYPE_H + +struct ipt_addrtype_info { + u_int16_t source; /* source-type mask */ + u_int16_t dest; /* dest-type mask */ + u_int32_t invert_source; + u_int32_t invert_dest; +}; + +#endif diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h new file mode 100644 index 000000000000..a4d6698723ac --- /dev/null +++ b/include/linux/netfilter_ipv4/ipt_realm.h @@ -0,0 +1,10 @@ +#ifndef _IPT_REALM_H +#define _IPT_REALM_H + +struct ipt_realm_info { + u_int32_t id; + u_int32_t mask; + u_int8_t invert; +}; + +#endif /* _IPT_REALM_H */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f79c67d6f281..c653647073f1 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -80,6 +80,9 @@ /* SGI IP22 aka Indy / Challenge S / Indigo 2 */ #define PORT_IP22ZILOG 56 +/* Sharp LH7a40x -- an ARM9 SoC series */ +#define PORT_LH7A40X 57 + #ifdef __KERNEL__ #include <linux/config.h> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1b33d607f276..f47163e84760 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1109,6 +1109,14 @@ static inline void nf_conntrack_get(struct nf_ct_info *nfct) if (nfct) atomic_inc(&nfct->master->use); } +static inline void nf_reset(struct sk_buff *skb) +{ + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug = 0; +#endif +} #ifdef CONFIG_BRIDGE_NETFILTER static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) @@ -1121,9 +1129,10 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) if (nf_bridge) atomic_inc(&nf_bridge->use); } -#endif - -#endif +#endif /* CONFIG_BRIDGE_NETFILTER */ +#else /* CONFIG_NETFILTER */ +static inline void nf_reset(struct sk_buff *skb) {} +#endif /* CONFIG_NETFILTER */ #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index ef193874f81a..fadfc6d7a87e 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -382,7 +382,7 @@ asmlinkage long sys_fchdir(unsigned int fd); asmlinkage long sys_rmdir(const char __user *pathname); asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user *buf, size_t len); asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, - qid_t id, caddr_t addr); + qid_t id, void __user *addr); asmlinkage long sys_getdents(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 4cb54379e85a..f94c7ac77c48 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -24,6 +24,27 @@ struct attribute_group { }; + +/** + * Use these macros to make defining attributes easier. See include/linux/device.h + * for examples.. + */ + +#define __ATTR(_name,_mode,_show,_store) { \ + .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .show = _show, \ + .store = _store, \ +} + +#define __ATTR_RO(_name) { \ + .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \ + .show = _name##_show, \ +} + +#define __ATTR_NULL { .attr = { .name = NULL } } + +#define attr_name(_attr) (_attr).attr.name + struct bin_attribute { struct attribute attr; size_t size; diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 39e2d22619dc..d95f58a553b0 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -262,8 +262,8 @@ struct tcp_opt { __u32 frto_highmark; /* snd_nxt when RTO occurred */ __u8 unused_pad; - __u8 queue_shrunk; /* Write queue has been shrunk recently.*/ __u8 defer_accept; /* User waits for some data after accept() */ + /* one byte hole, try to pack */ /* RTT measurement */ __u8 backoff; /* backoff */ @@ -297,7 +297,6 @@ struct tcp_opt { struct sk_buff_head out_of_order_queue; /* Out of order segments go here */ struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */ - struct sk_buff *send_head; /* Front of stuff to transmit */ __u32 rcv_wnd; /* Current receiver window */ __u32 rcv_wup; /* rcv_nxt on last window update sent */ @@ -371,8 +370,6 @@ struct tcp_opt { struct open_request *accept_queue; struct open_request *accept_queue_tail; - int write_pending; /* A write to socket waits to start. */ - unsigned int keepalive_time; /* time before keep alive takes place */ unsigned int keepalive_intvl; /* time interval between keep alive probes */ int linger2; diff --git a/include/net/esp.h b/include/net/esp.h index a513d14522ee..90cd94fad7d9 100644 --- a/include/net/esp.h +++ b/include/net/esp.h @@ -2,9 +2,14 @@ #define _NET_ESP_H #include <net/xfrm.h> +#include <asm/scatterlist.h> + +#define ESP_NUM_FAST_SG 4 struct esp_data { + struct scatterlist sgbuf[ESP_NUM_FAST_SG]; + /* Confidentiality */ struct { u8 *key; /* Key */ diff --git a/include/net/sock.h b/include/net/sock.h index 0ee6ccddca40..0398823e18ed 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -167,6 +167,9 @@ struct sock_common { * @sk_socket - Identd and reporting IO signals * @sk_user_data - RPC layer private data * @sk_owner - module that owns this socket + * @sk_send_head - front of stuff to transmit + * @sk_write_pending - a write to stream socket waits to start + * @sk_queue_shrunk - write queue has been shrunk recently * @sk_state_change - callback to indicate change in the state of the sock * @sk_data_ready - callback to indicate there is data to be processed * @sk_write_space - callback to indicate there is bf sending space available @@ -246,8 +249,12 @@ struct sock { struct timeval sk_stamp; struct socket *sk_socket; void *sk_user_data; + struct sk_buff *sk_send_head; struct module *sk_owner; + int sk_write_pending; void *sk_security; + __u8 sk_queue_shrunk; + /* three bytes hole, try to pack */ void (*sk_state_change)(struct sock *sk); void (*sk_data_ready)(struct sock *sk, int bytes); void (*sk_write_space)(struct sock *sk); @@ -434,6 +441,24 @@ static inline int sk_stream_memory_free(struct sock *sk) return sk->sk_wmem_queued < sk->sk_sndbuf; } +extern void sk_stream_rfree(struct sk_buff *skb); + +static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk) +{ + skb->sk = sk; + skb->destructor = sk_stream_rfree; + atomic_add(skb->truesize, &sk->sk_rmem_alloc); + sk->sk_forward_alloc -= skb->truesize; +} + +static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb) +{ + sk->sk_queue_shrunk = 1; + sk->sk_wmem_queued -= skb->truesize; + sk->sk_forward_alloc += skb->truesize; + __kfree_skb(skb); +} + /* The per-socket spinlock must be held here. */ #define sk_add_backlog(__sk, __skb) \ do { if (!(__sk)->sk_backlog.tail) { \ @@ -458,6 +483,11 @@ do { if (!(__sk)->sk_backlog.tail) { \ rc; \ }) +extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p); +extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p); +extern void sk_stream_wait_close(struct sock *sk, long timeo_p); +extern int sk_stream_error(struct sock *sk, int flags, int err); + extern int sk_wait_data(struct sock *sk, long *timeo); /* IP protocol blocks we attach to sockets. @@ -1067,6 +1097,20 @@ static inline void sk_wake_async(struct sock *sk, int how, int band) #define SOCK_MIN_SNDBUF 2048 #define SOCK_MIN_RCVBUF 256 +static inline void sk_stream_moderate_sndbuf(struct sock *sk) +{ + if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) { + sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued / 2); + sk->sk_sndbuf = max(sk->sk_sndbuf, SOCK_MIN_SNDBUF); + } +} + +#define sk_stream_for_retrans_queue(skb, sk) \ + for (skb = (sk)->sk_write_queue.next; \ + (skb != (sk)->sk_send_head) && \ + (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ + skb = skb->next) + /* * Default write policy as shown to user space via poll/select/SIGIO */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 3a323cd1e79f..22a62d58c24d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1186,13 +1186,6 @@ struct tcp_skb_cb { #define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0])) -#define for_retrans_queue(skb, sk, tp) \ - for (skb = (sk)->sk_write_queue.next; \ - (skb != (tp)->send_head) && \ - (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ - skb=skb->next) - - #include <net/tcp_ecn.h> /* This determines how many packets are "in the network" to the best @@ -1400,7 +1393,7 @@ tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now, int n tcp_minshall_check(tp)))); } -/* This checks if the data bearing packet SKB (usually tp->send_head) +/* This checks if the data bearing packet SKB (usually sk->sk_send_head) * should be put on the wire right now. */ static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb, @@ -1457,7 +1450,7 @@ static __inline__ void __tcp_push_pending_frames(struct sock *sk, unsigned cur_mss, int nonagle) { - struct sk_buff *skb = tp->send_head; + struct sk_buff *skb = sk->sk_send_head; if (skb) { if (!tcp_skb_is_last(sk, skb)) @@ -1477,7 +1470,7 @@ static __inline__ void tcp_push_pending_frames(struct sock *sk, static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_opt *tp) { - struct sk_buff *skb = tp->send_head; + struct sk_buff *skb = sk->sk_send_head; return (skb && tcp_snd_test(tp, skb, tcp_current_mss(sk, 1), @@ -1876,14 +1869,6 @@ static __inline__ void tcp_openreq_init(struct open_request *req, #define TCP_MEM_QUANTUM ((int)PAGE_SIZE) -static inline void tcp_free_skb(struct sock *sk, struct sk_buff *skb) -{ - tcp_sk(sk)->queue_shrunk = 1; - sk->sk_wmem_queued -= skb->truesize; - sk->sk_forward_alloc += skb->truesize; - __kfree_skb(skb); -} - extern void __tcp_mem_reclaim(struct sock *sk); extern int tcp_mem_schedule(struct sock *sk, int size, int kind); @@ -1901,14 +1886,6 @@ static inline void tcp_enter_memory_pressure(void) } } -static inline void tcp_moderate_sndbuf(struct sock *sk) -{ - if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) { - sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued / 2); - sk->sk_sndbuf = max(sk->sk_sndbuf, SOCK_MIN_SNDBUF); - } -} - static inline struct sk_buff *tcp_alloc_pskb(struct sock *sk, int size, int mem, int gfp) { struct sk_buff *skb = alloc_skb(size+MAX_TCP_HEADER, gfp); @@ -1923,7 +1900,7 @@ static inline struct sk_buff *tcp_alloc_pskb(struct sock *sk, int size, int mem, __kfree_skb(skb); } else { tcp_enter_memory_pressure(); - tcp_moderate_sndbuf(sk); + sk_stream_moderate_sndbuf(sk); } return NULL; } @@ -1942,7 +1919,7 @@ static inline struct page * tcp_alloc_page(struct sock *sk) return page; } tcp_enter_memory_pressure(); - tcp_moderate_sndbuf(sk); + sk_stream_moderate_sndbuf(sk); return NULL; } @@ -1951,20 +1928,10 @@ static inline void tcp_writequeue_purge(struct sock *sk) struct sk_buff *skb; while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) - tcp_free_skb(sk, skb); + sk_stream_free_skb(sk, skb); tcp_mem_reclaim(sk); } -extern void tcp_rfree(struct sk_buff *skb); - -static inline void tcp_set_owner_r(struct sk_buff *skb, struct sock *sk) -{ - skb->sk = sk; - skb->destructor = tcp_rfree; - atomic_add(skb->truesize, &sk->sk_rmem_alloc); - sk->sk_forward_alloc -= skb->truesize; -} - extern void tcp_listen_wlock(void); /* - We may sleep inside this lock. @@ -2049,8 +2016,8 @@ static inline int tcp_use_frto(const struct sock *sk) * unsent new data, and the advertised window should allow * sending it. */ - return (sysctl_tcp_frto && tp->send_head && - !after(TCP_SKB_CB(tp->send_head)->end_seq, + return (sysctl_tcp_frto && sk->sk_send_head && + !after(TCP_SKB_CB(sk->sk_send_head)->end_seq, tp->snd_una + tp->snd_wnd)); } diff --git a/kernel/module.c b/kernel/module.c index b96b1397422b..71a0944bddb1 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -980,6 +980,104 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, return ret; } + +/* + * /sys/module/foo/sections stuff + * J. Corbet <corbet@lwn.net> + */ +#ifdef CONFIG_KALLSYMS +static void module_sect_attrs_release(struct kobject *kobj) +{ + kfree(container_of(kobj, struct module_sections, kobj)); +} + +static ssize_t module_sect_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct module_sect_attr *sattr = + container_of(attr, struct module_sect_attr, attr); + return sprintf(buf, "0x%lx\n", sattr->address); +} + +static struct sysfs_ops module_sect_ops = { + .show = module_sect_show, +}; + +static struct kobj_type module_sect_ktype = { + .sysfs_ops = &module_sect_ops, + .release = module_sect_attrs_release, +}; + +static void add_sect_attrs(struct module *mod, unsigned int nsect, + char *secstrings, Elf_Shdr *sechdrs) +{ + unsigned int nloaded = 0, i; + struct module_sect_attr *sattr; + + if (!mod->mkobj) + return; + + /* Count loaded sections and allocate structures */ + for (i = 0; i < nsect; i++) + if (sechdrs[i].sh_flags & SHF_ALLOC) + nloaded++; + mod->sect_attrs = kmalloc(sizeof(struct module_sections) + + nloaded*sizeof(mod->sect_attrs->attrs[0]), GFP_KERNEL); + if (! mod->sect_attrs) + return; + + /* sections entry setup */ + memset(mod->sect_attrs, 0, sizeof(struct module_sections)); + if (kobject_set_name(&mod->sect_attrs->kobj, "sections")) + goto out; + mod->sect_attrs->kobj.parent = &mod->mkobj->kobj; + mod->sect_attrs->kobj.ktype = &module_sect_ktype; + if (kobject_register(&mod->sect_attrs->kobj)) + goto out; + + /* And the section attributes. */ + sattr = &mod->sect_attrs->attrs[0]; + for (i = 0; i < nsect; i++) { + if (! (sechdrs[i].sh_flags & SHF_ALLOC)) + continue; + sattr->address = sechdrs[i].sh_addr; + strlcpy(sattr->name, secstrings + sechdrs[i].sh_name, + MODULE_SECT_NAME_LEN); + sattr->attr.name = sattr->name; + sattr->attr.owner = mod; + sattr->attr.mode = S_IRUGO; + (void) sysfs_create_file(&mod->sect_attrs->kobj, &sattr->attr); + sattr++; + } + return; + out: + kfree(mod->sect_attrs); + mod->sect_attrs = NULL; +} + +static void remove_sect_attrs(struct module *mod) +{ + if (mod->sect_attrs) { + kobject_unregister(&mod->sect_attrs->kobj); + mod->sect_attrs = NULL; + } +} + + +#else +static inline void add_sect_attrs(struct module *mod, unsigned int nsect, + char *sectstrings, Elf_Shdr *sechdrs) +{ +} + +static inline void remove_sect_attrs(struct module *mod) +{ +} +#endif /* CONFIG_KALLSYMS */ + + + + #define to_module_attr(n) container_of(n, struct module_attribute, attr); static ssize_t module_attr_show(struct kobject *kobj, @@ -1098,6 +1196,7 @@ static void free_module(struct module *mod) list_del(&mod->list); spin_unlock_irq(&modlist_lock); + remove_sect_attrs(mod); mod_kobject_remove(mod); /* Arch-specific cleanup. */ @@ -1711,6 +1810,7 @@ static struct module *load_module(void __user *umod, / sizeof(struct kernel_param)); if (err < 0) goto arch_cleanup; + add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); /* Get rid of temporary copy */ vfree(hdr); diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c index d5b3e0a3f829..ad9a1bf4fc63 100644 --- a/lib/zlib_deflate/deflate.c +++ b/lib/zlib_deflate/deflate.c @@ -1262,7 +1262,7 @@ static block_state deflate_slow( return flush == Z_FINISH ? finish_done : block_done; } -extern int zlib_deflate_workspacesize(void) +int zlib_deflate_workspacesize(void) { return sizeof(deflate_workspace); } diff --git a/mm/swapfile.c b/mm/swapfile.c index 154d05795678..6422f1b8d810 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -652,7 +652,7 @@ static int try_to_unuse(unsigned int type) * open() method called) - so swap entries may be invisible * to swapoff for a while, then reappear - but that is rare. */ - while ((i = find_next_to_unuse(si, i))) { + while ((i = find_next_to_unuse(si, i)) != 0) { if (signal_pending(current)) { retval = -EINTR; break; diff --git a/net/core/dev.c b/net/core/dev.c index 9729210ca4cb..95a2b344e949 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1406,13 +1406,12 @@ int dev_queue_xmit(struct sk_buff *skb) Either shot noqueue qdisc, it is even simpler 8) */ if (dev->flags & IFF_UP) { - preempt_disable(); - int cpu = smp_processor_id(); + int cpu = get_cpu(); if (dev->xmit_lock_owner != cpu) { HARD_TX_LOCK_BH(dev, cpu); - preempt_enable(); + put_cpu(); if (!netif_queue_stopped(dev)) { if (netdev_nit) @@ -1430,7 +1429,7 @@ int dev_queue_xmit(struct sk_buff *skb) "queue packet!\n", dev->name); goto out_enetdown; } else { - preempt_enable(); + put_cpu(); /* Recursion is detected! It is possible, * unfortunately */ if (net_ratelimit()) diff --git a/net/core/sock.c b/net/core/sock.c index 289f5824e97c..992c2ab34c7a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1147,6 +1147,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) skb_queue_head_init(&sk->sk_write_queue); skb_queue_head_init(&sk->sk_error_queue); + sk->sk_send_head = NULL; + init_timer(&sk->sk_timer); sk->sk_allocation = GFP_KERNEL; @@ -1176,6 +1178,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_peercred.pid = 0; sk->sk_peercred.uid = -1; sk->sk_peercred.gid = -1; + sk->sk_write_pending = 0; sk->sk_rcvlowat = 1; sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; diff --git a/net/core/stream.c b/net/core/stream.c index 24a6f72a0594..d00c8d90565f 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/net.h> #include <linux/signal.h> +#include <linux/tcp.h> #include <linux/wait.h> #include <net/sock.h> @@ -39,3 +40,151 @@ void sk_stream_write_space(struct sock *sk) } EXPORT_SYMBOL(sk_stream_write_space); + +/** + * sk_stream_wait_connect - Wait for a socket to get into the connected state + * @sk - sock to wait on + * @timeo_p - for how long to wait + * + * Must be called with the socket locked. + */ +int sk_stream_wait_connect(struct sock *sk, long *timeo_p) +{ + struct task_struct *tsk = current; + DEFINE_WAIT(wait); + + while (1) { + if (sk->sk_err) + return sock_error(sk); + if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) + return -EPIPE; + if (!*timeo_p) + return -EAGAIN; + if (signal_pending(tsk)) + return sock_intr_errno(*timeo_p); + + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + sk->sk_write_pending++; + if (sk_wait_event(sk, timeo_p, + !((1 << sk->sk_state) & + ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)))) + break; + finish_wait(sk->sk_sleep, &wait); + sk->sk_write_pending--; + } + return 0; +} + +EXPORT_SYMBOL(sk_stream_wait_connect); + +/** + * sk_stream_closing - Return 1 if we still have things to send in our buffers. + * @sk - socket to verify + */ +static inline int sk_stream_closing(struct sock *sk) +{ + return (1 << sk->sk_state) & + (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK); +} + +void sk_stream_wait_close(struct sock *sk, long timeout) +{ + if (timeout) { + DEFINE_WAIT(wait); + + do { + prepare_to_wait(sk->sk_sleep, &wait, + TASK_INTERRUPTIBLE); + if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk))) + break; + } while (!signal_pending(current) && timeout); + + finish_wait(sk->sk_sleep, &wait); + } +} + +EXPORT_SYMBOL(sk_stream_wait_close); + +/** + * sk_stream_wait_memory - Wait for more memory for a socket + * @sk - socket to wait for memory + * @timeo_p - for how long + */ +int sk_stream_wait_memory(struct sock *sk, long *timeo_p) +{ + int err = 0; + long vm_wait = 0; + long current_timeo = *timeo_p; + DEFINE_WAIT(wait); + + if (sk_stream_memory_free(sk)) + current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2; + + while (1) { + set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); + + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + + if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) + goto do_error; + if (!*timeo_p) + goto do_nonblock; + if (signal_pending(current)) + goto do_interrupted; + clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); + if (sk_stream_memory_free(sk) && !vm_wait) + break; + + set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); + sk->sk_write_pending++; + sk_wait_event(sk, ¤t_timeo, sk_stream_memory_free(sk) && + vm_wait); + sk->sk_write_pending--; + + if (vm_wait) { + vm_wait -= current_timeo; + current_timeo = *timeo_p; + if (current_timeo != MAX_SCHEDULE_TIMEOUT && + (current_timeo -= vm_wait) < 0) + current_timeo = 0; + vm_wait = 0; + } + *timeo_p = current_timeo; + } +out: + finish_wait(sk->sk_sleep, &wait); + return err; + +do_error: + err = -EPIPE; + goto out; +do_nonblock: + err = -EAGAIN; + goto out; +do_interrupted: + err = sock_intr_errno(*timeo_p); + goto out; +} + +EXPORT_SYMBOL(sk_stream_wait_memory); + +void sk_stream_rfree(struct sk_buff *skb) +{ + struct sock *sk = skb->sk; + + atomic_sub(skb->truesize, &sk->sk_rmem_alloc); + sk->sk_forward_alloc += skb->truesize; +} + +EXPORT_SYMBOL(sk_stream_rfree); + +int sk_stream_error(struct sock *sk, int flags, int err) +{ + if (err == -EPIPE) + err = sock_error(sk) ? : -EPIPE; + if (err == -EPIPE && !(flags & MSG_NOSIGNAL)) + send_sig(SIGPIPE, current, 0); + return err; +} + +EXPORT_SYMBOL(sk_stream_error); diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index acecd602a2c8..2cd91612ed63 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -11,8 +11,6 @@ #include <net/icmp.h> #include <net/udp.h> -#define MAX_SG_ONSTACK 4 - /* decapsulation data for use when post-processing */ struct esp_decap_data { xfrm_address_t saddr; @@ -185,17 +183,16 @@ int esp_output(struct sk_buff **pskb) crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); do { - struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; - struct scatterlist *sg = sgbuf; + struct scatterlist *sg = &esp->sgbuf[0]; - if (unlikely(nfrags > MAX_SG_ONSTACK)) { + if (unlikely(nfrags > ESP_NUM_FAST_SG)) { sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); if (!sg) goto error; } skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen); crypto_cipher_encrypt(tfm, sg, sg, clen); - if (unlikely(sg != sgbuf)) + if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); } while (0); @@ -283,19 +280,18 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu { u8 nexthdr[2]; - struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; - struct scatterlist *sg = sgbuf; + struct scatterlist *sg = &esp->sgbuf[0]; u8 workbuf[60]; int padlen; - if (unlikely(nfrags > MAX_SG_ONSTACK)) { + if (unlikely(nfrags > ESP_NUM_FAST_SG)) { sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); if (!sg) goto out; } skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); - if (unlikely(sg != sgbuf)) + if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 4a227f51b2c1..0c2f8ca5ae83 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -643,13 +643,7 @@ int ipgre_rcv(struct sk_buff *skb) skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); ipgre_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipgre_lock); @@ -877,13 +871,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } } -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); IPTUNNEL_XMIT(); tunnel->recursion--; diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 2f71ed5cfcc9..5b473004fab9 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -202,17 +202,13 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) #ifdef CONFIG_NETFILTER_DEBUG nf_debug_ip_local_deliver(skb); - skb->nf_debug = 0; #endif /*CONFIG_NETFILTER_DEBUG*/ __skb_pull(skb, ihl); -#ifdef CONFIG_NETFILTER /* Free reference early: we don't need it any more, and it may hold ip_conntrack module loaded indefinitely. */ - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#endif /*CONFIG_NETFILTER*/ + nf_reset(skb); /* Point into the IP datagram, just past the header. */ skb->h.raw = skb->data; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 757b1d3f6aa2..98ba22404ac3 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -497,13 +497,7 @@ static int ipip_rcv(struct sk_buff *skb) skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); ipip_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip_lock); @@ -648,13 +642,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if ((iph->ttl = tiph->ttl) == 0) iph->ttl = old_iph->ttl; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); IPTUNNEL_XMIT(); tunnel->recursion--; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index a25e56077072..3aecdcf5e085 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1105,10 +1105,7 @@ static void ip_encap(struct sk_buff *skb, u32 saddr, u32 daddr) skb->h.ipiph = skb->nh.iph; skb->nh.iph = iph; memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#endif + nf_reset(skb); } static inline int ipmr_forward_finish(struct sk_buff *skb) @@ -1461,10 +1458,7 @@ int pim_rcv_v1(struct sk_buff * skb) skb->dst = NULL; ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len; ((struct net_device_stats*)reg_dev->priv)->rx_packets++; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#endif + nf_reset(skb); netif_rx(skb); dev_put(reg_dev); return 0; @@ -1520,10 +1514,7 @@ static int pim_rcv(struct sk_buff * skb) ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len; ((struct net_device_stats*)reg_dev->priv)->rx_packets++; skb->dst = NULL; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#endif + nf_reset(skb); netif_rx(skb); dev_put(reg_dev); return 0; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index f5a5110f97da..eaf79408bc03 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -603,5 +603,29 @@ config IP_NF_RAW <file:Documentation/modules.txt>. If unsure, say `N'. help +config IP_NF_MATCH_ADDRTYPE + tristate 'address type match support' + depends on IP_NF_IPTABLES + help + This option allows you to match what routing thinks of an address, + eg. UNICAST, LOCAL, BROADCAST, ... + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + +config IP_NF_MATCH_REALM + tristate 'realm match support' + depends on IP_NF_IPTABLES + select NET_CLS_ROUTE + help + This option adds a `realm' match, which allows you to use the realm + key from the routing subsytem inside iptables. + + This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option + in tc world. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + endmenu diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 52bedf2d7c62..bdb23fde133f 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -64,6 +64,8 @@ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index ae1bc2509dd2..4e8f4d83baf2 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -107,7 +107,7 @@ static int help(struct sk_buff *skb, exp->mask.dst.u.tcp.port = 0xFFFF; exp_amanda_info = &exp->help.exp_amanda_info; - exp_amanda_info->offset = data - amanda_buffer; + exp_amanda_info->offset = tmp - amanda_buffer; exp_amanda_info->port = port; exp_amanda_info->len = len; diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 1f47e9bbc4eb..00a89f4f8d8b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -174,13 +174,12 @@ static void destroy_expect(struct ip_conntrack_expect *exp) { DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(&exp->use)); - IP_NF_ASSERT(atomic_read(&exp->use)); + IP_NF_ASSERT(atomic_read(&exp->use) == 0); IP_NF_ASSERT(!timer_pending(&exp->timeout)); kfree(exp); } - inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp) { IP_NF_ASSERT(exp); @@ -716,7 +715,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", conntrack, expected); /* Welcome, Mr. Bond. We've been expecting you... */ - IP_NF_ASSERT(master_ct(conntrack)); __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = expected; expected->sibling = conntrack; @@ -949,9 +947,8 @@ ip_conntrack_expect_insert(struct ip_conntrack_expect *new, atomic_set(&new->use, 1); /* add to expected list for this connection */ - list_add(&new->expected_list, &related_to->sibling_list); + list_add_tail(&new->expected_list, &related_to->sibling_list); /* add to global list of expectations */ - list_prepend(&ip_conntrack_expect_list, &new->list); /* add and start timer if required */ if (related_to->helper->timeout) { @@ -1005,7 +1002,6 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect, } else if (related_to->helper->max_expected && related_to->expecting >= related_to->helper->max_expected) { - struct list_head *cur_item; /* old == NULL */ if (!(related_to->helper->flags & IP_CT_HELPER_F_REUSE_EXPECT)) { @@ -1031,21 +1027,14 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect, NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip)); /* choose the the oldest expectation to evict */ - list_for_each(cur_item, &related_to->sibling_list) { - struct ip_conntrack_expect *cur; - - cur = list_entry(cur_item, - struct ip_conntrack_expect, - expected_list); - if (cur->sibling == NULL) { - old = cur; + list_for_each_entry(old, &related_to->sibling_list, + expected_list) + if (old->sibling == NULL) break; - } - } - /* (!old) cannot happen, since related_to->expecting is the - * number of unconfirmed expects */ - IP_NF_ASSERT(old); + /* We cannot fail since related_to->expecting is the number + * of unconfirmed expectations */ + IP_NF_ASSERT(old && old->sibling == NULL); /* newnat14 does not reuse the real allocated memory * structures but rather unexpects the old and diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index fbe26d1ca0ad..80edac904188 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -503,7 +503,7 @@ static int init_or_cleanup(int init) if (ret < 0) goto cleanup_nothing; - proc = proc_net_create("ip_conntrack",0,list_conntracks); + proc = proc_net_create("ip_conntrack", 0440, list_conntracks); if (!proc) goto cleanup_init; proc->owner = THIS_MODULE; diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 3e5ca975459d..1c6b7810655a 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -528,6 +528,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, MUST_BE_WRITE_LOCKED(&ip_nat_lock); IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_POST_ROUTING + || hooknum == NF_IP_LOCAL_IN || hooknum == NF_IP_LOCAL_OUT); IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS); IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); @@ -816,7 +817,7 @@ do_bindings(struct ip_conntrack *ct, /* Have to grab read lock before sibling_list traversal */ READ_LOCK(&ip_conntrack_lock); - list_for_each(cur_item, &ct->sibling_list) { + list_for_each_prev(cur_item, &ct->sibling_list) { exp = list_entry(cur_item, struct ip_conntrack_expect, expected_list); @@ -899,10 +900,10 @@ icmp_reply_translation(struct sk_buff **pskb, /* Must be RELATED */ IP_NF_ASSERT((*pskb)->nfct - - (struct ip_conntrack *)(*pskb)->nfct->master + - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos == IP_CT_RELATED || (*pskb)->nfct - - (struct ip_conntrack *)(*pskb)->nfct->master + - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos == IP_CT_RELATED+IP_CT_IS_REPLY); /* Redirects on non-null nats must be dropped, else they'll diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2d433b69d099..a612865a5635 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1731,6 +1731,15 @@ static inline int print_name(const char *i, return 0; } +static inline int print_target(const struct ipt_target *t, + off_t start_offset, char *buffer, int length, + off_t *pos, unsigned int *count) +{ + if (t == &ipt_standard_target || t == &ipt_error_target) + return 0; + return print_name((char *)t, start_offset, buffer, length, pos, count); +} + static int ipt_get_tables(char *buffer, char **start, off_t offset, int length) { off_t pos = 0; @@ -1757,7 +1766,7 @@ static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) if (down_interruptible(&ipt_mutex) != 0) return 0; - LIST_FIND(&ipt_target, print_name, void *, + LIST_FIND(&ipt_target, print_target, struct ipt_target *, offset, buffer, length, &pos, &count); up(&ipt_mutex); diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/ipv4/netfilter/ipt_CLASSIFY.c index e7b300465532..9842e6e23184 100644 --- a/net/ipv4/netfilter/ipt_CLASSIFY.c +++ b/net/ipv4/netfilter/ipt_CLASSIFY.c @@ -54,15 +54,17 @@ checkentry(const char *tablename, return 0; } - if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) { - printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n"); + if (hook_mask & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | + (1 << NF_IP_POST_ROUTING))) { + printk(KERN_ERR "CLASSIFY: only valid in LOCAL_OUT, FORWARD " + "and POST_ROUTING.\n"); return 0; } if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "CLASSIFY: can only be called from " - "\"mangle\" table, not \"%s\".\n", - tablename); + printk(KERN_ERR "CLASSIFY: can only be called from " + "\"mangle\" table, not \"%s\".\n", + tablename); return 0; } diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index f6183f968b2b..b8018cb023ff 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -142,12 +142,8 @@ static void send_reset(struct sk_buff *oldskb, int hook) nskb->dst = &rt->u.dst; /* This packet will not be the same as the other: clear nf fields */ - nf_conntrack_put(nskb->nfct); - nskb->nfct = NULL; + nf_reset(nskb); nskb->nfcache = 0; -#ifdef CONFIG_NETFILTER_DEBUG - nskb->nf_debug = 0; -#endif nskb->nfmark = 0; #ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(nskb->nf_bridge); diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c new file mode 100644 index 000000000000..7392ba6bd23f --- /dev/null +++ b/net/ipv4/netfilter/ipt_addrtype.c @@ -0,0 +1,77 @@ +/* + * iptables module to match inet_addr_type() of an ip. + * + * Copyright (c) 2004 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/ip.h> +#include <net/route.h> + +#include <linux/netfilter_ipv4/ipt_addrtype.h> +#include <linux/netfilter_ipv4/ip_tables.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); +MODULE_DESCRIPTION("iptables addrtype match"); + +static inline int match_type(u_int32_t addr, u_int16_t mask) +{ + return !!(mask & (1 << inet_addr_type(addr))); +} + +static int match(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const void *matchinfo, + int offset, int *hotdrop) +{ + const struct ipt_addrtype_info *info = matchinfo; + const struct iphdr *iph = skb->nh.iph; + int ret = 1; + + if (info->source) + ret &= match_type(iph->saddr, info->source)^info->invert_source; + if (info->dest) + ret &= match_type(iph->daddr, info->dest)^info->invert_dest; + + return ret; +} + +static int checkentry(const char *tablename, const struct ipt_ip *ip, + void *matchinfo, unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) { + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.", + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info))); + return 0; + } + + return 1; +} + +static struct ipt_match addrtype_match = { + .name = "addrtype", + .match = match, + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static int __init init(void) +{ + return ipt_register_match(&addrtype_match); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&addrtype_match); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c index bed83c79e3cc..ee9881ece49f 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/ipv4/netfilter/ipt_helper.c @@ -41,17 +41,17 @@ match(const struct sk_buff *skb, struct ip_conntrack_expect *exp; struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; - int ret = 0; + int ret = info->invert; ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); if (!ct) { DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); - return 0; + return ret; } if (!ct->master) { DEBUGP("ipt_helper: conntrack %p has no master\n", ct); - return 0; + return ret; } exp = ct->master; @@ -71,8 +71,11 @@ match(const struct sk_buff *skb, DEBUGP("master's name = %s , info->name = %s\n", exp->expectant->helper->name, info->name); - ret = !strncmp(exp->expectant->helper->name, info->name, - strlen(exp->expectant->helper->name)) ^ info->invert; + if (info->name[0] == '\0') + ret ^= 1; + else + ret ^= !strncmp(exp->expectant->helper->name, info->name, + strlen(exp->expectant->helper->name)); out_unlock: READ_UNLOCK(&ip_conntrack_lock); return ret; @@ -92,10 +95,6 @@ static int check(const char *tablename, if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) return 0; - /* verify that we actually should match anything */ - if ( strlen(info->name) == 0 ) - return 0; - return 1; } @@ -108,7 +107,6 @@ static struct ipt_match helper_match = { static int __init init(void) { - need_ip_conntrack(); return ipt_register_match(&helper_match); } diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 91c3fd3f1f8f..3b9065e06381 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c @@ -184,7 +184,15 @@ checkentry(const char *tablename, IPT_ALIGN(sizeof(struct ipt_owner_info))); return 0; } - +#ifdef CONFIG_SMP + /* files->file_lock can not be used in a BH */ + if (((struct ipt_owner_info *)matchinfo)->match + & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) { + printk("ipt_owner: pid, sid and command matching is broken " + "on SMP.\n"); + return 0; + } +#endif return 1; } diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/ipv4/netfilter/ipt_realm.c new file mode 100644 index 000000000000..54a6897ebaa6 --- /dev/null +++ b/net/ipv4/netfilter/ipt_realm.c @@ -0,0 +1,76 @@ +/* IP tables module for matching the routing realm + * + * $Id: ipt_realm.c,v 1.3 2004/03/05 13:25:40 laforge Exp $ + * + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <net/route.h> + +#include <linux/netfilter_ipv4/ipt_realm.h> +#include <linux/netfilter_ipv4/ip_tables.h> + +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("iptables realm match"); + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_realm_info *info = matchinfo; + struct dst_entry *dst = skb->dst; + + return (info->id == (dst->tclassid & info->mask)) ^ info->invert; +} + +static int check(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (hook_mask + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | + (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " + "LOCAL_IN or FORWARD.\n"); + return 0; + } + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { + printk("ipt_realm: invalid matchsize.\n"); + return 0; + } + return 1; +} + +static struct ipt_match realm_match = { + .name = "realm", + .match = match, + .checkentry = check, + .me = THIS_MODULE +}; + +static int __init init(void) +{ + return ipt_register_match(&realm_match); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&realm_match); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 1c3d96b5f7f7..b5b43b277fe2 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -173,7 +173,9 @@ ipt_local_hook(unsigned int hook, if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE && ((*pskb)->nh.iph->saddr != saddr || (*pskb)->nh.iph->daddr != daddr +#ifdef CONFIG_IP_ROUTE_FWMARK || (*pskb)->nfmark != nfmark +#endif || (*pskb)->nh.iph->tos != tos)) return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 4c2266d2013b..0fd648ac0df3 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -32,43 +32,64 @@ static struct struct ipt_replace repl; struct ipt_standard entries[2]; struct ipt_error term; -} initial_table __initdata -= { { "raw", RAW_VALID_HOOKS, 3, - sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), - { [NF_IP_PRE_ROUTING] 0, - [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) }, - { [NF_IP_PRE_ROUTING] 0, - [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) }, - 0, NULL, { } }, - { - /* PRE_ROUTING */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_OUT */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } } - }, - /* ERROR */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_error), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __initdata = { + .repl = { + .name = "raw", + .valid_hooks = RAW_VALID_HOOKS, + .num_entries = 3, + .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), + .hook_entry = { + [NF_IP_PRE_ROUTING] = 0, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, + .underflow = { + [NF_IP_PRE_ROUTING] = 0, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, + }, + .entries = { + /* PRE_ROUTING */ + { + .entry = { + .target_offset = sizeof(struct ipt_entry), + .next_offset = sizeof(struct ipt_standard), + }, + .target = { + .target = { + .u.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), + }, + .verdict = -NF_ACCEPT - 1, + }, + }, + + /* LOCAL_OUT */ + { + .entry = { + .target_offset = sizeof(struct ipt_entry), + .next_offset = sizeof(struct ipt_standard), + }, + .target = { + .target = { + .u.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), + }, + .verdict = -NF_ACCEPT - 1, + }, + }, + }, + /* ERROR */ + .term = { + .entry = { + .target_offset = sizeof(struct ipt_entry), + .next_offset = sizeof(struct ipt_error), + }, + .target = { + .target = { + .u.user = { + .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)), + .name = IPT_ERROR_TARGET, + }, + }, + .errorname = "ERROR", + }, + } }; static struct ipt_table packet_raw = { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cf0adc2f1a89..bf17df099f66 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -333,7 +333,7 @@ int tcp_mem_schedule(struct sock *sk, int size, int kind) suppress_allocation: if (!kind) { - tcp_moderate_sndbuf(sk); + sk_stream_moderate_sndbuf(sk); /* Fail only if socket is _under_ its sndbuf. * In this case we cannot block, so that we have to fail. @@ -360,14 +360,6 @@ void __tcp_mem_reclaim(struct sock *sk) } } -void tcp_rfree(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - - atomic_sub(skb->truesize, &sk->sk_rmem_alloc); - sk->sk_forward_alloc += skb->truesize; -} - /* * LISTEN is a special case for poll.. */ @@ -636,102 +628,6 @@ static void tcp_listen_stop (struct sock *sk) BUG_TRAP(!sk->sk_ack_backlog); } -/* - * Wait for a socket to get into the connected state - * - * Note: Must be called with the socket locked. - */ -static int wait_for_tcp_connect(struct sock *sk, int flags, long *timeo_p) -{ - struct tcp_opt *tp = tcp_sk(sk); - struct task_struct *tsk = current; - DEFINE_WAIT(wait); - - while ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) { - if (sk->sk_err) - return sock_error(sk); - if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) - return -EPIPE; - if (!*timeo_p) - return -EAGAIN; - if (signal_pending(tsk)) - return sock_intr_errno(*timeo_p); - - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - tp->write_pending++; - - release_sock(sk); - *timeo_p = schedule_timeout(*timeo_p); - lock_sock(sk); - - finish_wait(sk->sk_sleep, &wait); - tp->write_pending--; - } - return 0; -} - -/* - * Wait for more memory for a socket - */ -static int wait_for_tcp_memory(struct sock *sk, long *timeo) -{ - struct tcp_opt *tp = tcp_sk(sk); - int err = 0; - long vm_wait = 0; - long current_timeo = *timeo; - DEFINE_WAIT(wait); - - if (sk_stream_memory_free(sk)) - current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2; - - for (;;) { - set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); - - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - - if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) - goto do_error; - if (!*timeo) - goto do_nonblock; - if (signal_pending(current)) - goto do_interrupted; - clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); - if (sk_stream_memory_free(sk) && !vm_wait) - break; - - set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); - tp->write_pending++; - release_sock(sk); - if (!sk_stream_memory_free(sk) || vm_wait) - current_timeo = schedule_timeout(current_timeo); - lock_sock(sk); - tp->write_pending--; - - if (vm_wait) { - vm_wait -= current_timeo; - current_timeo = *timeo; - if (current_timeo != MAX_SCHEDULE_TIMEOUT && - (current_timeo -= vm_wait) < 0) - current_timeo = 0; - vm_wait = 0; - } - *timeo = current_timeo; - } -out: - finish_wait(sk->sk_sleep, &wait); - return err; - -do_error: - err = -EPIPE; - goto out; -do_nonblock: - err = -EAGAIN; - goto out; -do_interrupted: - err = sock_intr_errno(*timeo); - goto out; -} - static inline void fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size) { @@ -763,8 +659,8 @@ static inline void skb_entail(struct sock *sk, struct tcp_opt *tp, TCP_SKB_CB(skb)->sacked = 0; __skb_queue_tail(&sk->sk_write_queue, skb); sk_charge_skb(sk, skb); - if (!tp->send_head) - tp->send_head = skb; + if (!sk->sk_send_head) + sk->sk_send_head = skb; else if (tp->nonagle&TCP_NAGLE_PUSH) tp->nonagle &= ~TCP_NAGLE_PUSH; } @@ -782,7 +678,7 @@ static inline void tcp_mark_urg(struct tcp_opt *tp, int flags, static inline void tcp_push(struct sock *sk, struct tcp_opt *tp, int flags, int mss_now, int nonagle) { - if (tp->send_head) { + if (sk->sk_send_head) { struct sk_buff *skb = sk->sk_write_queue.prev; if (!(flags & MSG_MORE) || forced_push(tp)) tcp_mark_push(tp, skb); @@ -792,15 +688,6 @@ static inline void tcp_push(struct sock *sk, struct tcp_opt *tp, int flags, } } -static int tcp_error(struct sock *sk, int flags, int err) -{ - if (err == -EPIPE) - err = sock_error(sk) ? : -EPIPE; - if (err == -EPIPE && !(flags & MSG_NOSIGNAL)) - send_sig(SIGPIPE, current, 0); - return err; -} - static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags) { @@ -812,7 +699,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse /* Wait for a connection to finish. */ if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) - if ((err = wait_for_tcp_connect(sk, 0, &timeo)) != 0) + if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) goto out_err; clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); @@ -831,7 +718,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse int offset = poffset % PAGE_SIZE; int size = min_t(size_t, psize, PAGE_SIZE - offset); - if (!tp->send_head || (copy = mss_now - skb->len) <= 0) { + if (!sk->sk_send_head || (copy = mss_now - skb->len) <= 0) { new_segment: if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf; @@ -879,7 +766,7 @@ new_segment: if (forced_push(tp)) { tcp_mark_push(tp, skb); __tcp_push_pending_frames(sk, tp, mss_now, TCP_NAGLE_PUSH); - } else if (skb == tp->send_head) + } else if (skb == sk->sk_send_head) tcp_push_one(sk, mss_now); continue; @@ -889,7 +776,7 @@ wait_for_memory: if (copied) tcp_push(sk, tp, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); - if ((err = wait_for_tcp_memory(sk, &timeo)) != 0) + if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) goto do_error; mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); @@ -904,7 +791,7 @@ do_error: if (copied) goto out; out_err: - return tcp_error(sk, flags, err); + return sk_stream_error(sk, flags, err); } ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, @@ -965,7 +852,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* Wait for a connection to finish. */ if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) - if ((err = wait_for_tcp_connect(sk, flags, &timeo)) != 0) + if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) goto out_err; /* This should be in poll */ @@ -993,7 +880,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, skb = sk->sk_write_queue.prev; - if (!tp->send_head || + if (!sk->sk_send_head || (copy = mss_now - skb->len) <= 0) { new_segment: @@ -1122,7 +1009,7 @@ new_segment: if (forced_push(tp)) { tcp_mark_push(tp, skb); __tcp_push_pending_frames(sk, tp, mss_now, TCP_NAGLE_PUSH); - } else if (skb == tp->send_head) + } else if (skb == sk->sk_send_head) tcp_push_one(sk, mss_now); continue; @@ -1132,7 +1019,7 @@ wait_for_memory: if (copied) tcp_push(sk, tp, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); - if ((err = wait_for_tcp_memory(sk, &timeo)) != 0) + if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) goto do_error; mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); @@ -1148,17 +1035,17 @@ out: do_fault: if (!skb->len) { - if (tp->send_head == skb) - tp->send_head = NULL; + if (sk->sk_send_head == skb) + sk->sk_send_head = NULL; __skb_unlink(skb, skb->list); - tcp_free_skb(sk, skb); + sk_stream_free_skb(sk, skb); } do_error: if (copied) goto out; out_err: - err = tcp_error(sk, flags, err); + err = sk_stream_error(sk, flags, err); TCP_CHECK_TIMER(sk); release_sock(sk); return err; @@ -1747,17 +1634,6 @@ void tcp_shutdown(struct sock *sk, int how) } } - -/* - * Return 1 if we still have things to send in our buffers. - */ - -static inline int closing(struct sock *sk) -{ - return (1 << sk->sk_state) & - (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK); -} - static __inline__ void tcp_kill_sk_queues(struct sock *sk) { /* First the read buffer. */ @@ -1900,22 +1776,7 @@ void tcp_close(struct sock *sk, long timeout) tcp_send_fin(sk); } - if (timeout) { - struct task_struct *tsk = current; - DEFINE_WAIT(wait); - - do { - prepare_to_wait(sk->sk_sleep, &wait, - TASK_INTERRUPTIBLE); - if (!closing(sk)) - break; - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); - } while (!signal_pending(tsk) && timeout); - - finish_wait(sk->sk_sleep, &wait); - } + sk_stream_wait_close(sk, timeout); adjudge_to_death: /* It is the last release_sock in its life. It will remove backlog. */ @@ -2046,7 +1907,7 @@ int tcp_disconnect(struct sock *sk, int flags) tcp_set_ca_state(tp, TCP_CA_Open); tcp_clear_retrans(tp); tcp_delack_init(tp); - tp->send_head = NULL; + sk->sk_send_head = NULL; tp->saw_tstamp = 0; tcp_sack_reset(tp); __sk_dst_reset(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cd72986ebc50..65afca6006b2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1009,7 +1009,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ if (after(end_seq, tp->high_seq)) flag |= FLAG_DATA_LOST; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { u8 sacked = TCP_SKB_CB(skb)->sacked; int in_sack; @@ -1113,7 +1113,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ if (lost_retrans && tp->ca_state == TCP_CA_Recovery) { struct sk_buff *skb; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { if (after(TCP_SKB_CB(skb)->seq, lost_retrans)) break; if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) @@ -1179,7 +1179,7 @@ void tcp_enter_frto(struct sock *sk) tp->undo_marker = tp->snd_una; tp->undo_retrans = 0; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { TCP_SKB_CB(skb)->sacked &= ~TCPCB_RETRANS; } tcp_sync_left_out(tp); @@ -1202,7 +1202,7 @@ static void tcp_enter_frto_loss(struct sock *sk) tp->lost_out = 0; tp->fackets_out = 0; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { cnt++; TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) { @@ -1275,7 +1275,7 @@ void tcp_enter_loss(struct sock *sk, int how) if (!how) tp->undo_marker = tp->snd_una; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { cnt++; if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS) tp->undo_marker = 0; @@ -1518,7 +1518,7 @@ tcp_mark_head_lost(struct sock *sk, struct tcp_opt *tp, int packets, u32 high_se BUG_TRAP(cnt <= tp->packets_out); - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { if (--cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq)) break; if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { @@ -1550,7 +1550,7 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_opt *tp) if (tcp_head_timedout(sk, tp)) { struct sk_buff *skb; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { if (tcp_skb_timedout(tp, skb) && !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; @@ -1719,7 +1719,7 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp) { if (tcp_may_undo(tp)) { struct sk_buff *skb; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; } DBGUNDO(sk, tp, "partial loss"); @@ -2328,7 +2328,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) int acked = 0; __s32 seq_rtt = -1; - while ((skb = skb_peek(&sk->sk_write_queue)) && skb != tp->send_head) { + while ((skb = skb_peek(&sk->sk_write_queue)) && skb != sk->sk_send_head) { struct tcp_skb_cb *scb = TCP_SKB_CB(skb); __u8 sacked = scb->sacked; @@ -2376,7 +2376,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) tp->fackets_out--; tp->packets_out--; __skb_unlink(skb, skb->list); - tcp_free_skb(sk, skb); + sk_stream_free_skb(sk, skb); } if (acked&FLAG_ACKED) { @@ -2416,7 +2416,7 @@ static void tcp_ack_probe(struct sock *sk) /* Was it a usable window open? */ - if (!after(TCP_SKB_CB(tp->send_head)->end_seq, + if (!after(TCP_SKB_CB(sk->sk_send_head)->end_seq, tp->snd_una + tp->snd_wnd)) { tp->backoff = 0; tcp_clear_xmit_timer(sk, TCP_TIME_PROBE0); @@ -2857,7 +2857,7 @@ no_queue: * being used to time the probes, and is probably far higher than * it needs to be for normal retransmission. */ - if (tp->send_head) + if (sk->sk_send_head) tcp_ack_probe(sk); return 1; @@ -3461,7 +3461,7 @@ queue_and_out: if (tcp_prune_queue(sk) < 0 || !tcp_rmem_schedule(sk, skb)) goto drop; } - tcp_set_owner_r(skb, sk); + sk_stream_set_owner_r(skb, sk); __skb_queue_tail(&sk->sk_receive_queue, skb); } tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; @@ -3542,7 +3542,7 @@ drop: SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n", tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); - tcp_set_owner_r(skb, sk); + sk_stream_set_owner_r(skb, sk); if (!skb_peek(&tp->out_of_order_queue)) { /* Initial out of order segment, build 1 SACK. */ @@ -3681,7 +3681,7 @@ tcp_collapse(struct sock *sk, struct sk_buff *head, memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start; __skb_insert(nskb, skb->prev, skb, skb->list); - tcp_set_owner_r(nskb, sk); + sk_stream_set_owner_r(nskb, sk); /* Copy data, releasing collapsed skbs. */ while (copy > 0) { @@ -3837,7 +3837,7 @@ void tcp_cwnd_application_limited(struct sock *sk) /* When incoming ACK allowed to free some skb from write_queue, - * we remember this event in flag tp->queue_shrunk and wake up socket + * we remember this event in flag sk->sk_queue_shrunk and wake up socket * on the exit from tcp input handler. * * PROBLEM: sndbuf expansion does not work well with largesend. @@ -3865,10 +3865,8 @@ static void tcp_new_space(struct sock *sk) static inline void tcp_check_space(struct sock *sk) { - struct tcp_opt *tp = tcp_sk(sk); - - if (tp->queue_shrunk) { - tp->queue_shrunk = 0; + if (sk->sk_queue_shrunk) { + sk->sk_queue_shrunk = 0; if (sk->sk_socket && test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) tcp_new_space(sk); @@ -3887,8 +3885,7 @@ static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb) static __inline__ void tcp_data_snd_check(struct sock *sk) { - struct tcp_opt *tp = tcp_sk(sk); - struct sk_buff *skb = tp->send_head; + struct sk_buff *skb = sk->sk_send_head; if (skb != NULL) __tcp_data_snd_check(sk, skb); @@ -4242,7 +4239,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, /* Bulk data transfer: receiver */ __skb_pull(skb,tcp_header_len); __skb_queue_tail(&sk->sk_receive_queue, skb); - tcp_set_owner_r(skb, sk); + sk_stream_set_owner_r(skb, sk); tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; } @@ -4482,7 +4479,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, sk_wake_async(sk, 0, POLL_OUT); } - if (tp->write_pending || tp->defer_accept || tp->ack.pingpong) { + if (sk->sk_write_pending || tp->defer_accept || tp->ack.pingpong) { /* Save one ACK. Data will be ready after * several ticks, if write_pending is set. * diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 3af98bd3ff3e..dacd76e33133 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -718,6 +718,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, sock_reset_flag(newsk, SOCK_DONE); newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; + newsk->sk_send_head = NULL; newsk->sk_callback_lock = RW_LOCK_UNLOCKED; skb_queue_head_init(&newsk->sk_error_queue); newsk->sk_write_space = sk_stream_write_space; @@ -775,7 +776,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, tcp_set_ca_state(newtp, TCP_CA_Open); tcp_init_xmit_timers(newsk); skb_queue_head_init(&newtp->out_of_order_queue); - newtp->send_head = NULL; newtp->rcv_wup = req->rcv_isn + 1; newtp->write_seq = req->snt_isn + 1; newtp->pushed_seq = newtp->write_seq; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ad0c2ac89a1a..7d6eca0cd01e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -48,9 +48,9 @@ int sysctl_tcp_retrans_collapse = 1; static __inline__ void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb) { - tp->send_head = skb->next; - if (tp->send_head == (struct sk_buff *)&sk->sk_write_queue) - tp->send_head = NULL; + sk->sk_send_head = skb->next; + if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue) + sk->sk_send_head = NULL; tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; if (tp->packets_out++ == 0) tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto); @@ -329,8 +329,8 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) sk_charge_skb(sk, skb); /* Queue it, remembering where we must start sending. */ - if (tp->send_head == NULL) - tp->send_head = skb; + if (sk->sk_send_head == NULL) + sk->sk_send_head = skb; } /* Send _single_ skb sitting at the send head. This function requires @@ -339,13 +339,13 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) void tcp_push_one(struct sock *sk, unsigned cur_mss) { struct tcp_opt *tp = tcp_sk(sk); - struct sk_buff *skb = tp->send_head; + struct sk_buff *skb = sk->sk_send_head; if (tcp_snd_test(tp, skb, cur_mss, TCP_NAGLE_PUSH)) { /* Send it out now. */ TCP_SKB_CB(skb)->when = tcp_time_stamp; if (!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation))) { - tp->send_head = NULL; + sk->sk_send_head = NULL; tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; if (tp->packets_out++ == 0) tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto); @@ -572,8 +572,10 @@ int tcp_write_xmit(struct sock *sk, int nonagle) */ mss_now = tcp_current_mss(sk, 1); - while((skb = tp->send_head) && - tcp_snd_test(tp, skb, mss_now, tcp_skb_is_last(sk, skb) ? nonagle : TCP_NAGLE_PUSH)) { + while ((skb = sk->sk_send_head) && + tcp_snd_test(tp, skb, mss_now, + tcp_skb_is_last(sk, skb) ? nonagle : + TCP_NAGLE_PUSH)) { if (skb->len > mss_now) { if (tcp_fragment(sk, skb, mss_now)) break; @@ -593,7 +595,7 @@ int tcp_write_xmit(struct sock *sk, int nonagle) return 0; } - return !tp->packets_out && tp->send_head; + return !tp->packets_out && sk->sk_send_head; } return 0; } @@ -763,7 +765,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m */ if (tp->fackets_out) tp->fackets_out--; - tcp_free_skb(sk, next_skb); + sk_stream_free_skb(sk, next_skb); tp->packets_out--; } } @@ -779,7 +781,7 @@ void tcp_simple_retransmit(struct sock *sk) unsigned int mss = tcp_current_mss(sk, 0); int lost = 0; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { if (skb->len > mss && !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) { if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) { @@ -865,7 +867,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) /* Collapse two adjacent packets if worthwhile and we can. */ if(!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) && (skb->len < (cur_mss >> 1)) && - (skb->next != tp->send_head) && + (skb->next != sk->sk_send_head) && (skb->next != (struct sk_buff *)&sk->sk_write_queue) && (skb_shinfo(skb)->nr_frags == 0 && skb_shinfo(skb->next)->nr_frags == 0) && (sysctl_tcp_retrans_collapse != 0)) @@ -940,7 +942,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) /* First pass: retransmit lost packets. */ if (packet_cnt) { - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { __u8 sacked = TCP_SKB_CB(skb)->sacked; if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) @@ -988,7 +990,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) packet_cnt = 0; - for_retrans_queue(skb, sk, tp) { + sk_stream_for_retrans_queue(skb, sk) { if(++packet_cnt > tp->fackets_out) break; @@ -1025,7 +1027,7 @@ void tcp_send_fin(struct sock *sk) */ mss_now = tcp_current_mss(sk, 1); - if(tp->send_head != NULL) { + if (sk->sk_send_head != NULL) { TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN; TCP_SKB_CB(skb)->end_seq++; tp->write_seq++; @@ -1104,7 +1106,7 @@ int tcp_send_synack(struct sock *sk) return -ENOMEM; __skb_unlink(skb, &sk->sk_write_queue); __skb_queue_head(&sk->sk_write_queue, nskb); - tcp_free_skb(sk, skb); + sk_stream_free_skb(sk, skb); sk_charge_skb(sk, nskb); skb = nskb; } @@ -1404,7 +1406,7 @@ int tcp_write_wakeup(struct sock *sk) struct tcp_opt *tp = tcp_sk(sk); struct sk_buff *skb; - if ((skb = tp->send_head) != NULL && + if ((skb = sk->sk_send_head) != NULL && before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) { int err; int mss = tcp_current_mss(sk, 0); @@ -1458,7 +1460,7 @@ void tcp_send_probe0(struct sock *sk) err = tcp_write_wakeup(sk); - if (tp->packets_out || !tp->send_head) { + if (tp->packets_out || !sk->sk_send_head) { /* Cancel probe timer, if it is not required. */ tp->probes_out = 0; tp->backoff = 0; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index cab2678b1958..44615198e6a1 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -269,7 +269,7 @@ static void tcp_probe_timer(struct sock *sk) struct tcp_opt *tp = tcp_sk(sk); int max_probes; - if (tp->packets_out || !tp->send_head) { + if (tp->packets_out || !sk->sk_send_head) { tp->probes_out = 0; return; } @@ -606,7 +606,7 @@ static void tcp_keepalive_timer (unsigned long data) elapsed = keepalive_time_when(tp); /* It is alive without keepalive 8) */ - if (tp->packets_out || tp->send_head) + if (tp->packets_out || sk->sk_send_head) goto resched; elapsed = tcp_time_stamp - tp->rcv_tstamp; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index fb2720697d96..8682cf13402a 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -38,8 +38,6 @@ #include <net/ipv6.h> #include <linux/icmpv6.h> -#define MAX_SG_ONSTACK 4 - int esp6_output(struct sk_buff **pskb) { int err; @@ -151,17 +149,16 @@ int esp6_output(struct sk_buff **pskb) crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); do { - struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; - struct scatterlist *sg = sgbuf; + struct scatterlist *sg = &esp->sgbuf[0]; - if (unlikely(nfrags > MAX_SG_ONSTACK)) { + if (unlikely(nfrags > ESP_NUM_FAST_SG)) { sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); if (!sg) goto error; } skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen); crypto_cipher_encrypt(tfm, sg, sg, clen); - if (unlikely(sg != sgbuf)) + if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); } while (0); @@ -259,12 +256,11 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b { u8 nexthdr[2]; - struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; - struct scatterlist *sg = sgbuf; + struct scatterlist *sg = &esp->sgbuf[0]; u8 padlen; u8 *prevhdr; - if (unlikely(nfrags > MAX_SG_ONSTACK)) { + if (unlikely(nfrags > ESP_NUM_FAST_SG)) { sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); if (!sg) { ret = -ENOMEM; @@ -273,7 +269,7 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b } skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); - if (unlikely(sg != sgbuf)) + if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9e5677dd45a2..0c8db0391a78 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -722,13 +722,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) ipv6h->nexthdr = proto; ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src); ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst); -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); pkt_len = skb->len; err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 223212888321..d2ce00d81d4c 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1845,6 +1845,15 @@ static inline int print_name(const char *i, return 0; } +static inline int print_target(const struct ip6t_target *t, + off_t start_offset, char *buffer, int length, + off_t *pos, unsigned int *count) +{ + if (t == &ip6t_standard_target || t == &ip6t_error_target) + return 0; + return print_name((char *)t, start_offset, buffer, length, pos, count); +} + static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length) { off_t pos = 0; @@ -1871,7 +1880,7 @@ static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length if (down_interruptible(&ip6t_mutex) != 0) return 0; - LIST_FIND(&ip6t_target, print_name, char *, + LIST_FIND(&ip6t_target, print_target, struct ip6t_target *, offset, buffer, length, &pos, &count); up(&ip6t_mutex); diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 0bb9c661b73c..272257b3b637 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -143,7 +143,14 @@ checkentry(const char *tablename, if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info))) return 0; - +#ifdef CONFIG_SMP + /* files->file_lock can not be used in a BH */ + if (((struct ip6t_owner_info *)matchinfo)->match + & (IP6T_OWNER_PID|IP6T_OWNER_SID)) { + printk("ip6t_owner: pid and sid matching is broken on SMP.\n"); + return 0; + } +#endif return 1; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 2fac873fdd3d..2958bb9c76fe 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -388,13 +388,7 @@ static int ipip6_rcv(struct sk_buff *skb) skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); ipip6_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip6_lock); @@ -580,13 +574,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if ((iph->ttl = tiph->ttl) == 0) iph->ttl = iph6->hop_limit; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); IPTUNNEL_XMIT(); tunnel->recursion--; diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8931426e0243..293655830d98 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -242,6 +242,7 @@ config NET_CLS_TCINDEX config NET_CLS_ROUTE4 tristate "Routing table based classifier" depends on NET_CLS + select NET_CLS_ROUTE help If you say Y here, you will be able to classify outgoing packets according to the route table entry they matched. If unsure, say Y. @@ -251,8 +252,7 @@ config NET_CLS_ROUTE4 config NET_CLS_ROUTE bool - depends on NET_CLS_ROUTE4 - default y + default n config NET_CLS_FW tristate "Firewall based classifier" diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 491b510b0782..d1b683952499 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -990,7 +990,7 @@ static int sctp_error(struct sock *sk, int flags, int err) * Note: This function could use a rewrite especially when explicit * connect support comes in. */ -/* BUG: We do not implement the equivalent of wait_for_tcp_memory(). */ +/* BUG: We do not implement the equivalent of sk_stream_wait_memory(). */ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *); diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 95dfeef913f1..4f80fec4f5c7 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -931,6 +931,13 @@ static int __init snd_pmac_detect(pmac_t *chip) chip->freq_table = tumbler_freqs; chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ } + if (device_is_compatible(sound, "AOAKeylargo")) { + /* Seems to support the stock AWACS frequencies, but has + a snapper mixer */ + chip->model = PMAC_SNAPPER; + // chip->can_byte_swap = 0; /* FIXME: check this */ + chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ + } prop = (unsigned int *)get_property(sound, "device-id", 0); if (prop) chip->device_id = *prop; |
