## Automatically generated incremental diff ## From: linux-2.6.2-rc2 ## To: linux-2.6.2-rc3 ## Robot: $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $ diff -urN linux-2.6.2-rc2/Documentation/fb/modedb.txt linux-2.6.2-rc3/Documentation/fb/modedb.txt --- linux-2.6.2-rc2/Documentation/fb/modedb.txt 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/Documentation/fb/modedb.txt 2004-01-30 18:49:19.000000000 -0800 @@ -51,10 +51,10 @@ Drivers that support modedb boot options Boot Name Cards Supported - ami - Amiga chipset frame buffer + amifb - Amiga chipset frame buffer aty128fb - ATI Rage128 / Pro frame buffer atyfb - ATI Mach64 frame buffer - tdfx - 3D Fx frame buffer + tdfxfb - 3D Fx frame buffer tridentfb - Trident (Cyber)blade chipset frame buffer BTW, only a few drivers use this at the moment. Others are to follow diff -urN linux-2.6.2-rc2/Documentation/i2c/porting-clients linux-2.6.2-rc3/Documentation/i2c/porting-clients --- linux-2.6.2-rc2/Documentation/i2c/porting-clients 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/Documentation/i2c/porting-clients 2004-01-08 22:59:19.000000000 -0800 @@ -92,10 +92,7 @@ i2c_get_clientdata(client) instead. * [Interface] Init function should not print anything. Make sure - there is a MODULE_LICENSE() line. MODULE_PARM() is replaced - by module_param(). Note that module_param has a third parameter, - that you should set to 0 by default. See include/linux/moduleparam.h - for details. + there is a MODULE_LICENSE() line. Coding policy: diff -urN linux-2.6.2-rc2/Documentation/kernel-parameters.txt linux-2.6.2-rc3/Documentation/kernel-parameters.txt --- linux-2.6.2-rc2/Documentation/kernel-parameters.txt 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/Documentation/kernel-parameters.txt 2004-01-30 18:49:19.000000000 -0800 @@ -96,6 +96,23 @@ ht -- run only enough ACPI to enable Hyper Threading See also Documentation/pm.txt. + acpi_pic_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode + Format: { level | edge } + level Force PIC-mode SCI to Level Trigger (default) + edge Force PIC-mode SCI to Edge Trigge + + acpi_irq_balance [HW,ACPI] ACPI will balance active IRQs + default in APIC mode + + acpi_irq_nobalance [HW,ACPI] ACPI will not move active IRQs (default) + default in PIC mode + + acpi_irq_pci= [HW,ACPI] If irq_balance, Clear listed IRQs for use by PCI + Format: ,... + + acpi_irq_isa= [HW,ACPI] If irq_balance, Mark listed IRQs used by ISA + Format: ,... + ad1816= [HW,OSS] Format: ,,, See also Documentation/sound/oss/AD1816. diff -urN linux-2.6.2-rc2/Makefile linux-2.6.2-rc3/Makefile --- linux-2.6.2-rc2/Makefile 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/Makefile 2004-01-30 18:49:19.000000000 -0800 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 2 -EXTRAVERSION =-rc2 +EXTRAVERSION =-rc3 # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -825,8 +825,15 @@ -name '*.[chS]' -print ) endef -quiet_cmd_cscope = MAKE $@ -cmd_cscope = $(all-sources) | cscope -k -b -i - +quiet_cmd_cscope-file = FILELST cscope.files + cmd_cscope-file = $(all-sources) > cscope.files + +quiet_cmd_cscope = MAKE cscope.out + cmd_cscope = cscope -k -b + +cscope: FORCE + $(call cmd,cscope-file) + $(call cmd,cscope) quiet_cmd_TAGS = MAKE $@ cmd_TAGS = $(all-sources) | etags - @@ -840,9 +847,6 @@ $(all-sources) | xargs ctags $$CTAGSF -a endef -cscope: FORCE - $(call cmd,cscope) - TAGS: FORCE $(call cmd,TAGS) diff -urN linux-2.6.2-rc2/arch/arm/configs/cerfcube_defconfig linux-2.6.2-rc3/arch/arm/configs/cerfcube_defconfig --- linux-2.6.2-rc2/arch/arm/configs/cerfcube_defconfig 2004-01-08 22:59:04.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/configs/cerfcube_defconfig 2004-01-30 18:49:19.000000000 -0800 @@ -2,66 +2,94 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y # # Loadable module support # CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y # # System Type # +# CONFIG_ARCH_ADIFCC is not set # CONFIG_ARCH_ANAKIN is not set -# 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_PXA is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_RPC is not set CONFIG_ARCH_SA1100=y # CONFIG_ARCH_SHARK is not set # -# Archimedes/A5000 Implementations +# CLPS711X/EP721X Implementations # # -# Archimedes/A5000 Implementations (select only ONE) +# Epxa10db # -# 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 + +# +# IOP3xx Implementation Options +# +# CONFIG_ARCH_IOP310 is not set +# CONFIG_ARCH_IOP321 is not set + +# +# IOP3xx Chipset Features +# + +# +# Intel PXA250/210 Implementations +# # # SA11x0 Implementations # # CONFIG_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=y @@ -69,13 +97,17 @@ CONFIG_SA1100_CERF_FLASH_16MB=y # CONFIG_SA1100_CERF_FLASH_32MB is not set # CONFIG_SA1100_CERF_CPLD is not set +# CONFIG_SA1100_H3100 is not set # CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 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_BADGE4 is not set # CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HACKKIT is not set # CONFIG_SA1100_HUW_WEBPANEL is not set # CONFIG_SA1100_ITSY is not set # CONFIG_SA1100_LART is not set @@ -83,84 +115,81 @@ # CONFIG_SA1100_OMNIMETER is not set # CONFIG_SA1100_PANGOLIN is not set # CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON 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=y -CONFIG_SA1100_USB_NETLINK=y -CONFIG_SA1100_USB_CHAR=y +# CONFIG_SA1100_STORK is not set +# CONFIG_SA1100_SSP is not set +CONFIG_SA1100_USB=m +CONFIG_SA1100_USB_NETLINK=m +# CONFIG_SA1100_USB_CHAR is not set # -# CLPS711X/EP721X Implementations +# Processor Type # -# 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_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_SA1100=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4=y +CONFIG_CPU_CACHE_V4WB=y +CONFIG_CPU_TLB_V4WB=y +CONFIG_CPU_MINICACHE=y # -# Processor Type +# Processor Features # -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# 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_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -CONFIG_CPU_SA1100=y -# CONFIG_ARM_THUMB is not set -CONFIG_DISCONTIGMEM=y # # General setup # -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set +CONFIG_DISCONTIGMEM=y +CONFIG_ISA=y +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_SA1110=y +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_24_API=y CONFIG_HOTPLUG=y # # PCMCIA/CardBus support # -CONFIG_PCMCIA=y +CONFIG_PCMCIA=m +# CONFIG_PCMCIA_DEBUG is not set # CONFIG_I82365 is not set # CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -CONFIG_PCMCIA_SA1100=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y +CONFIG_PCMCIA_SA1100=m # # At least one math emulation must be selected # -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set +# CONFIG_FPE_NWFPE is not set +CONFIG_FPE_FASTFPE=y CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set +CONFIG_PM=y +# CONFIG_PREEMPT is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0 root=/dev/mtdblock3 rw mem=32M" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="console=ttySA0,38400 root=/dev/mtdblock3 rootfstype=jffs2 rw mem=32M init=/linuxrc" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -177,17 +206,19 @@ 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_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set # # User Modules And Translation Layers # -CONFIG_MTD_CHAR=y +CONFIG_MTD_CHAR=m CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers @@ -198,6 +229,7 @@ # CONFIG_MTD_CFI_ADV_OPTIONS is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -206,47 +238,25 @@ # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_SUN_UFLASH is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_TQM8XXL is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_L440GX is not set # CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set CONFIG_MTD_SA1100=y -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_EDB7312 is not set # # Self-contained MTD device drivers # -# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_LART is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -254,24 +264,19 @@ # CONFIG_MTD_NAND is not set # -# Plug and Play configuration +# Plug and Play support # # 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_BLK_DEV_DAC960 is not set -CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -279,47 +284,52 @@ # 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_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -CONFIG_FILTER=y CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set # +# SCTP Configuration (EXPERIMENTAL) # -# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 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 @@ -332,8 +342,9 @@ # CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -344,45 +355,35 @@ # 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_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=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_CERF_CS8900A=y +# CONFIG_MII is not set +# CONFIG_SMC91X 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set +CONFIG_NET_PCI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_CS8900=m # 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 + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -390,13 +391,12 @@ # Wireless LAN (non-hamradio) # # CONFIG_NET_RADIO is not set +# CONFIG_HOSTAP 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 # @@ -407,17 +407,7 @@ # # PCMCIA network device support # -CONFIG_NET_PCMCIA=y -# CONFIG_PCMCIA_3C589 is not set -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -CONFIG_PCMCIA_PCNET=m -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -# CONFIG_NET_PCMCIA_RADIO is not set +# CONFIG_NET_PCMCIA is not set # # Amateur Radio support @@ -430,113 +420,110 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# Bluetooth support # -CONFIG_IDE=y +# CONFIG_BT is not set # -# IDE, ATA and ATAPI Block devices +# ATA/ATAPI/MFM/RLL support # +CONFIG_IDE=y CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDEDISK=m # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECS=m # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set # CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device 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 +# CONFIG_ISDN_BOOL is not set # -# Input core support +# Input device support # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_TSLIBDEV is not set # CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# 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_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_SA1100=y CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=9600 -# 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_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=32 -# CONFIG_UCB1200 is not set -# CONFIG_TOUCHSCREEN_UCB1200 is not set -# CONFIG_AUDIO_UCB1200 is not set -# CONFIG_ADC_UCB1200 is not set -# CONFIG_TOUCHSCREEN_H3600 is not set -# CONFIG_PROFILER is not set -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set # # I2C support @@ -544,56 +531,68 @@ # 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_BIT_SA1100_UCB1200 is not set - -# -# Other L3 adapters +# I2C Algorithms # -# CONFIG_L3_SA1111 is not set # -# L3 driver support +# I2C Hardware Bus support # -# CONFIG_L3_DRV_UDA1341 is not set -# CONFIG_BIT_SA1100_GPIO is not set # -# Mice +# I2C Hardware Sensors Chip support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +# CONFIG_I2C_SENSOR is not set # -# Joysticks +# L3 serial bus support # -# CONFIG_INPUT_GAMEPORT is not set +CONFIG_L3=m # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_SA1100_WATCHDOG=m +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_SA1100_RTC=y +# CONFIG_GEN_RTC is not set +# CONFIG_SA1100_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -605,6 +604,8 @@ # # PCMCIA character devices # +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices @@ -612,94 +613,133 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# # File systems # -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=m # CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # 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_BEFS_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=y -CONFIG_MSDOS_FS=y -CONFIG_UMSDOS_FS=y -CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set # 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_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_VXFS_FS 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=y -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=y +CONFIG_NFS_FS=m CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=m CONFIG_LOCKD_V4=y -# CONFIG_SMB_FS is not set +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS 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_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +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=y -# CONFIG_SMB_NLS is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +CONFIG_SMB_NLS=y CONFIG_NLS=y # # Native Language Support # CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=m # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -720,8 +760,9 @@ # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ISO8859_1=m # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -737,15 +778,16 @@ # CONFIG_NLS_UTF8 is not set # -# Console drivers +# Graphics support # -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set +# CONFIG_FB is not set # -# Frame-buffer support +# Console display driver support # -# CONFIG_FB is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # # Sound @@ -753,121 +795,52 @@ # CONFIG_SOUND is not set # -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers +# Misc devices # -# 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 # -# USB Device Class drivers +# Multimedia Capabilities Port drivers # -# 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_JUMPSHOT 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_ACM is not set -# CONFIG_USB_PRINTER is not set +# CONFIG_MCP is not set # -# USB Human Interface Devices (HID) +# Console Switches # +# CONFIG_SWITCHES is not set # -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# 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 - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB 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 - -# -# USB port drivers +# USB support # -# CONFIG_USB_USS720 is not set +# CONFIG_USB_GADGET is not set # -# USB Serial Converter support +# Kernel hacking # -# 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_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_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_OMNINET is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Bluetooth support +# Cryptographic options # -# CONFIG_BT is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_NO_PGT_CACHE is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -urN linux-2.6.2-rc2/arch/arm/kernel/asm-offsets.c linux-2.6.2-rc3/arch/arm/kernel/asm-offsets.c --- linux-2.6.2-rc2/arch/arm/kernel/asm-offsets.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/kernel/asm-offsets.c 2004-01-30 18:49:19.000000000 -0800 @@ -45,7 +45,6 @@ int main(void) { - DEFINE(TSK_USED_MATH, offsetof(struct task_struct, used_math)); DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); diff -urN linux-2.6.2-rc2/arch/arm/kernel/entry-armv.S linux-2.6.2-rc3/arch/arm/kernel/entry-armv.S --- linux-2.6.2-rc2/arch/arm/kernel/entry-armv.S 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/kernel/entry-armv.S 2004-01-30 18:49:19.000000000 -0800 @@ -673,48 +673,6 @@ and r2, r6, #31 @ int mode b bad_mode -#if 1 /* defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE */ - /* The FPE is always present */ - .equ fpe_not_present, fpundefinstr -#else -wfs_mask_data: .word 0x0e200110 @ WFS/RFS - .word 0x0fef0fff - .word 0x0d000100 @ LDF [sp]/STF [sp] - .word 0x0d000100 @ LDF [fp]/STF [fp] - .word 0x0f000f00 - -/* We get here if an undefined instruction happens and the floating - * point emulator is not present. If the offending instruction was - * a WFS, we just perform a normal return as if we had emulated the - * operation. This is a hack to allow some basic userland binaries - * to run so that the emulator module proper can be loaded. --philb - */ -fpe_not_present: - adr r10, wfs_mask_data - ldmia r10, {r4, r5, r6, r7, r8} - ldr r10, [sp, #S_PC] @ Load PC - sub r10, r10, #4 - mask_pc r10, r10 - ldrt r10, [r10] @ get instruction - and r5, r10, r5 - teq r5, r4 @ Is it WFS? - moveq pc, r9 - and r5, r10, r8 - teq r5, r6 @ Is it LDF/STF on sp or fp? - teqne r5, r7 - movne pc, lr - tst r10, #0x00200000 @ Does it have WB - moveq pc, r9 - and r4, r10, #255 @ get offset - and r6, r10, #0x000f0000 - tst r10, #0x00800000 @ +/- - ldr r5, [sp, r6, lsr #14] @ Load reg - rsbeq r4, r4, #0 - add r5, r5, r4, lsl #2 - str r5, [sp, r6, lsr #14] @ Save reg - mov pc, r9 -#endif - /* * SVC mode handlers */ @@ -963,23 +921,46 @@ * co-processor instructions. However, we have to watch out * for the ARM6/ARM7 SWI bug. * - * Emulators may wish to make use of the instruction value we - * prepared for them in r0. + * Emulators may wish to make use of the following registers: + * r0 - instruction opcode. + * r10 - this threads thread_info structure. */ call_fpe: enable_irq r10 @ Enable interrupts tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) - and r10, r0, #0x0f000000 @ mask out op-code bits - teqne r10, #0x0f000000 @ SWI (ARM6/7 bug)? + and r8, r0, #0x0f000000 @ mask out op-code bits + teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? #endif moveq pc, lr -do_fpe: get_thread_info r10 @ get current thread - ldr r4, [r10, #TI_TASK] @ get current task - mov r8, #1 - strb r8, [r4, #TSK_USED_MATH] @ set current->used_math - ldr r4, .LCfp + get_thread_info r10 @ get current thread + and r8, r0, #0x00000f00 @ mask out CP number + mov r7, #1 + add r6, r10, #TI_USED_CP + strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] + add pc, pc, r8, lsr #6 + mov r0, r0 + + mov pc, lr @ CP#0 + b do_fpe @ CP#1 (FPE) + b do_fpe @ CP#2 (FPE) + mov pc, lr @ CP#3 + mov pc, lr @ CP#4 + mov pc, lr @ CP#5 + mov pc, lr @ CP#6 + mov pc, lr @ CP#7 + mov pc, lr @ CP#8 + mov pc, lr @ CP#9 + mov pc, lr @ CP#10 (VFP) + mov pc, lr @ CP#11 (VFP) + mov pc, lr @ CP#12 + mov pc, lr @ CP#13 + mov pc, lr @ CP#14 (Debug) + mov pc, lr @ CP#15 (Control) + +do_fpe: ldr r4, .LCfp add r10, r10, #TI_FPSTATE @ r10 = workspace ldr pc, [r4] @ Call FP module USR entry point + /* * The FP module is called with these registers set: * r0 = instruction @@ -989,6 +970,11 @@ * lr = unrecognised FP instruction return address */ + .data +ENTRY(fp_enter) + .word fpundefinstr + .text + fpundefinstr: mov r0, sp adrsvc al, lr, ret_from_exception b do_undefinstr @@ -1016,10 +1002,6 @@ mov why, #0 b ret_to_user - .data -ENTRY(fp_enter) - .word fpe_not_present - .text /* * Register switch for ARMv3 and ARMv4 processors * r0 = previous thread_info, r1 = next thread_info diff -urN linux-2.6.2-rc2/arch/arm/kernel/process.c linux-2.6.2-rc3/arch/arm/kernel/process.c --- linux-2.6.2-rc2/arch/arm/kernel/process.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/kernel/process.c 2004-01-30 18:49:19.000000000 -0800 @@ -307,8 +307,7 @@ struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; - tsk->used_math = 0; - + memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); fp_init(&thread->fpstate); } @@ -344,12 +343,12 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { struct thread_info *thread = current_thread_info(); - int used_math = current->used_math; + int used_math = thread->used_cp[1] | thread->used_cp[2]; if (used_math) memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); - return used_math; + return used_math != 0; } /* diff -urN linux-2.6.2-rc2/arch/arm/kernel/ptrace.c linux-2.6.2-rc3/arch/arm/kernel/ptrace.c --- linux-2.6.2-rc2/arch/arm/kernel/ptrace.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/kernel/ptrace.c 2004-01-30 18:49:19.000000000 -0800 @@ -602,8 +602,9 @@ */ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { - tsk->used_math = 1; - return copy_from_user(&tsk->thread_info->fpstate, ufp, + struct thread_info *thread = tsk->thread_info; + thread->used_cp[1] = thread->used_cp[2] = 1; + return copy_from_user(&thread->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff -urN linux-2.6.2-rc2/arch/arm/lib/csumpartial.S linux-2.6.2-rc3/arch/arm/lib/csumpartial.S --- linux-2.6.2-rc2/arch/arm/lib/csumpartial.S 2004-01-08 23:00:13.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/lib/csumpartial.S 2004-01-30 18:49:19.000000000 -0800 @@ -41,7 +41,7 @@ tst buf, #1 @ odd address? ldrneb td0, [buf], #1 subne len, len, #1 - adcnes sum, sum, td0, lsl #byte(1) + adcnes sum, sum, td0, put_byte_1 .less4: tst len, #6 beq .less8_byte @@ -68,7 +68,7 @@ .less8_byte: tst len, #1 @ odd number of bytes ldrneb td0, [buf], #1 @ include last byte - adcnes sum, sum, td0, lsl #byte(0) @ update checksum + adcnes sum, sum, td0, put_byte_0 @ update checksum .done: adc r0, sum, #0 @ collect up the last carry ldr td0, [sp], #4 @@ -80,7 +80,7 @@ .not_aligned: tst buf, #1 @ odd address ldrneb td0, [buf], #1 @ make even subne len, len, #1 - adcnes sum, sum, td0, lsl #byte(1) @ update checksum + adcnes sum, sum, td0, put_byte_1 @ update checksum tst buf, #2 @ 32-bit aligned? #if __LINUX_ARM_ARCH__ >= 4 diff -urN linux-2.6.2-rc2/arch/arm/lib/csumpartialcopygeneric.S linux-2.6.2-rc3/arch/arm/lib/csumpartialcopygeneric.S --- linux-2.6.2-rc2/arch/arm/lib/csumpartialcopygeneric.S 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/lib/csumpartialcopygeneric.S 2004-01-30 18:49:19.000000000 -0800 @@ -36,16 +36,16 @@ load1b ip sub len, len, #1 - adcs sum, sum, ip, lsl #byte(1) @ update checksum + adcs sum, sum, ip, put_byte_1 @ update checksum strb ip, [dst], #1 tst dst, #2 moveq pc, lr @ dst is now 32bit aligned .dst_16bit: load2b r8, ip sub len, len, #2 - adcs sum, sum, r8, lsl #byte(0) + adcs sum, sum, r8, put_byte_0 strb r8, [dst], #1 - adcs sum, sum, ip, lsl #byte(1) + adcs sum, sum, ip, put_byte_1 strb ip, [dst], #1 mov pc, lr @ dst is now 32bit aligned @@ -63,16 +63,16 @@ /* Align dst */ load1b ip sub len, len, #1 - adcs sum, sum, ip, lsl #byte(1) @ update checksum + adcs sum, sum, ip, put_byte_1 @ update checksum strb ip, [dst], #1 tst len, #6 beq .less8_byteonly 1: load2b r8, ip sub len, len, #2 - adcs sum, sum, r8, lsl #byte(0) + adcs sum, sum, r8, put_byte_0 strb r8, [dst], #1 - adcs sum, sum, ip, lsl #byte(1) + adcs sum, sum, ip, put_byte_1 strb ip, [dst], #1 .less8_aligned: tst len, #6 bne 1b @@ -80,7 +80,7 @@ tst len, #1 beq .done load1b r8 - adcs sum, sum, r8, lsl #byte(0) @ update checksum + adcs sum, sum, r8, put_byte_0 @ update checksum strb r8, [dst], #1 b .done @@ -139,17 +139,17 @@ beq .done load1l r4 tst len, #2 - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 beq .exit adcs sum, sum, r4, push #16 strb r5, [dst], #1 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 strb r5, [dst], #1 - mov r5, r4, lsr #byte(2) + mov r5, r4, get_byte_2 .exit: tst len, #1 strneb r5, [dst], #1 andne r5, r5, #255 - adcnes sum, sum, r5, lsl #byte(0) + adcnes sum, sum, r5, put_byte_0 /* * If the dst pointer was not 16-bit aligned, we @@ -213,14 +213,14 @@ mov r4, r5, pull #8 4: ands len, len, #3 beq .done - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 tst len, #2 beq .exit adcs sum, sum, r4, push #16 strb r5, [dst], #1 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 strb r5, [dst], #1 - mov r5, r4, lsr #byte(2) + mov r5, r4, get_byte_2 b .exit .src2_aligned: mov r4, r5, pull #16 @@ -265,12 +265,12 @@ mov r4, r5, pull #16 4: ands len, len, #3 beq .done - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 tst len, #2 beq .exit adcs sum, sum, r4 strb r5, [dst], #1 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 strb r5, [dst], #1 tst len, #1 beq .done @@ -319,14 +319,14 @@ mov r4, r5, pull #24 4: ands len, len, #3 beq .done - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 tst len, #2 beq .exit strb r5, [dst], #1 adcs sum, sum, r4 load1l r4 - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 strb r5, [dst], #1 adcs sum, sum, r4, push #24 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 b .exit diff -urN linux-2.6.2-rc2/arch/arm/lib/io-readsb.S linux-2.6.2-rc3/arch/arm/lib/io-readsb.S --- linux-2.6.2-rc2/arch/arm/lib/io-readsb.S 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/lib/io-readsb.S 2004-01-30 18:49:19.000000000 -0800 @@ -37,35 +37,35 @@ .insb_16_lp: ldrb r3, [r0] ldrb r4, [r0] ldrb r5, [r0] - mov r3, r3, lsl #byte(0) + mov r3, r3, put_byte_0 ldrb r6, [r0] - orr r3, r3, r4, lsl #byte(1) + orr r3, r3, r4, put_byte_1 ldrb r4, [r0] - orr r3, r3, r5, lsl #byte(2) + orr r3, r3, r5, put_byte_2 ldrb r5, [r0] - orr r3, r3, r6, lsl #byte(3) + orr r3, r3, r6, put_byte_3 ldrb r6, [r0] - mov r4, r4, lsl #byte(0) + mov r4, r4, put_byte_0 ldrb ip, [r0] - orr r4, r4, r5, lsl #byte(1) + orr r4, r4, r5, put_byte_1 ldrb r5, [r0] - orr r4, r4, r6, lsl #byte(2) + orr r4, r4, r6, put_byte_2 ldrb r6, [r0] - orr r4, r4, ip, lsl #byte(3) + orr r4, r4, ip, put_byte_3 ldrb ip, [r0] - mov r5, r5, lsl #byte(0) + mov r5, r5, put_byte_0 ldrb lr, [r0] - orr r5, r5, r6, lsl #byte(1) + orr r5, r5, r6, put_byte_1 ldrb r6, [r0] - orr r5, r5, ip, lsl #byte(2) + orr r5, r5, ip, put_byte_2 ldrb ip, [r0] - orr r5, r5, lr, lsl #byte(3) + orr r5, r5, lr, put_byte_3 ldrb lr, [r0] - mov r6, r6, lsl #byte(0) - orr r6, r6, ip, lsl #byte(1) + mov r6, r6, put_byte_0 + orr r6, r6, ip, put_byte_1 ldrb ip, [r0] - orr r6, r6, lr, lsl #byte(2) - orr r6, r6, ip, lsl #byte(3) + orr r6, r6, lr, put_byte_2 + orr r6, r6, ip, put_byte_3 stmia r1!, {r3 - r6} subs r2, r2, #16 @@ -80,19 +80,19 @@ ldrb r3, [r0] ldrb r4, [r0] ldrb r5, [r0] - mov r3, r3, lsl #byte(0) + mov r3, r3, put_byte_0 ldrb r6, [r0] - orr r3, r3, r4, lsl #byte(1) + orr r3, r3, r4, put_byte_1 ldrb r4, [r0] - orr r3, r3, r5, lsl #byte(2) + orr r3, r3, r5, put_byte_2 ldrb r5, [r0] - orr r3, r3, r6, lsl #byte(3) + orr r3, r3, r6, put_byte_3 ldrb r6, [r0] - mov r4, r4, lsl #byte(0) + mov r4, r4, put_byte_0 ldrb ip, [r0] - orr r4, r4, r5, lsl #byte(1) - orr r4, r4, r6, lsl #byte(2) - orr r4, r4, ip, lsl #byte(3) + orr r4, r4, r5, put_byte_1 + orr r4, r4, r6, put_byte_2 + orr r4, r4, ip, put_byte_3 stmia r1!, {r3, r4} .insb_no_8: tst r2, #4 @@ -102,10 +102,10 @@ ldrb r4, [r0] ldrb r5, [r0] ldrb r6, [r0] - mov r3, r3, lsl #byte(0) - orr r3, r3, r4, lsl #byte(1) - orr r3, r3, r5, lsl #byte(2) - orr r3, r3, r6, lsl #byte(3) + mov r3, r3, put_byte_0 + orr r3, r3, r4, put_byte_1 + orr r3, r3, r5, put_byte_2 + orr r3, r3, r6, put_byte_3 str r3, [r1], #4 .insb_no_4: ands r2, r2, #3 diff -urN linux-2.6.2-rc2/arch/arm/lib/uaccess.S linux-2.6.2-rc3/arch/arm/lib/uaccess.S --- linux-2.6.2-rc2/arch/arm/lib/uaccess.S 2004-01-08 22:59:05.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/lib/uaccess.S 2004-01-30 18:49:19.000000000 -0800 @@ -183,14 +183,14 @@ strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_1fupi -.c2u_1nowords: mov r3, r7, lsr #byte(1) +.c2u_1nowords: mov r3, r7, get_byte_1 teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - movge r3, r7, lsr #byte(2) + movge r3, r7, get_byte_2 USER( strgebt r3, [r0], #1) @ May fault - movgt r3, r7, lsr #byte(3) + movgt r3, r7, get_byte_3 USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished @@ -250,12 +250,12 @@ strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_2fupi -.c2u_2nowords: mov r3, r7, lsr #byte(2) +.c2u_2nowords: mov r3, r7, get_byte_2 teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - movge r3, r7, lsr #byte(3) + movge r3, r7, get_byte_3 USER( strgebt r3, [r0], #1) @ May fault ldrgtb r3, [r1], #0 USER( strgtbt r3, [r0], #1) @ May fault @@ -317,7 +317,7 @@ strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_3fupi -.c2u_3nowords: mov r3, r7, lsr #byte(3) +.c2u_3nowords: mov r3, r7, get_byte_3 teq ip, #0 beq .c2u_finished cmp ip, #2 @@ -496,14 +496,14 @@ strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_1fupi -.cfu_1nowords: mov r3, r7, lsr #byte(1) +.cfu_1nowords: mov r3, r7, get_byte_1 teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 - movge r3, r7, lsr #byte(2) + movge r3, r7, get_byte_2 strgeb r3, [r0], #1 - movgt r3, r7, lsr #byte(3) + movgt r3, r7, get_byte_3 strgtb r3, [r0], #1 b .cfu_finished @@ -563,12 +563,12 @@ strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_2fupi -.cfu_2nowords: mov r3, r7, lsr #byte(2) +.cfu_2nowords: mov r3, r7, get_byte_2 teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 - movge r3, r7, lsr #byte(3) + movge r3, r7, get_byte_3 strgeb r3, [r0], #1 USER( ldrgtbt r3, [r1], #0) @ May fault strgtb r3, [r0], #1 @@ -630,7 +630,7 @@ strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_3fupi -.cfu_3nowords: mov r3, r7, lsr #byte(3) +.cfu_3nowords: mov r3, r7, get_byte_3 teq ip, #0 beq .cfu_finished cmp ip, #2 diff -urN linux-2.6.2-rc2/arch/arm/mach-sa1100/cerf.c linux-2.6.2-rc3/arch/arm/mach-sa1100/cerf.c --- linux-2.6.2-rc2/arch/arm/mach-sa1100/cerf.c 2004-01-08 22:59:27.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/mach-sa1100/cerf.c 2004-01-30 18:49:19.000000000 -0800 @@ -1,48 +1,61 @@ /* * linux/arch/arm/mach-sa1100/cerf.c + * + * 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. + * + * Apr-2003 : Removed some old PDA crud [FB] + * Oct-2003 : Added uart2 resource [FB] + * Jan-2004 : Removed io map for flash [FB] */ + #include #include #include #include +#include #include #include #include +#include #include #include #include +#include #include "generic.h" +static struct resource cerfuart2_resources[] = { + [0] = { + .start = 0x80030000, + .end = 0x8003ffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device cerfuart2_device = { + .name = "sa11x0-uart", + .id = 2, + .num_resources = ARRAY_SIZE(cerfuart2_resources), + .resource = cerfuart2_resources, +}; + +static struct platform_device *cerf_devices[] __initdata = { + &cerfuart2_device, +}; static void __init cerf_init_irq(void) { sa1100_init_irq(); - - /* Need to register these as rising edge interrupts - * For standard 16550 serial driver support - * Basically - I copied it from pfs168.c :) - */ -#ifdef CONFIG_SA1100_CERF_CPLD - /* PDA Full serial port */ - set_irq_type(IRQ_GPIO3, IRQT_RISING); - /* PDA Bluetooth */ - set_irq_type(IRQ_GPIO2, IRQT_RISING); -#endif /* CONFIG_SA1100_CERF_CPLD */ - - set_irq_type(IRQ_GPIO_UCB1200_IRQ, IRQT_RISING); + set_irq_type(CERF_ETH_IRQ, IRQT_RISING); } static struct map_desc cerf_io_desc[] __initdata = { /* virtual physical length type */ { 0xf0000000, 0x08000000, 0x00100000, MT_DEVICE } /* Crystal Ethernet Chip */ -#ifdef CONFIG_SA1100_CERF_CPLD - ,{ 0xf1000000, 0x40000000, 0x00100000, MT_DEVICE }, /* CPLD Chip */ - { 0xf2000000, 0x10000000, 0x00100000, MT_DEVICE }, /* CerfPDA Bluetooth */ - { 0xf3000000, 0x18000000, 0x00100000, MT_DEVICE } /* CerfPDA Serial */ -#endif }; static void __init cerf_map_io(void) @@ -51,21 +64,30 @@ iotable_init(cerf_io_desc, ARRAY_SIZE(cerf_io_desc)); sa1100_register_uart(0, 3); -#ifdef CONFIG_SA1100_CERF_IRDA_ENABLED - sa1100_register_uart(1, 1); -#else - sa1100_register_uart(1, 2); + sa1100_register_uart(1, 2); /* disable this and the uart2 device for sa1100_fir */ sa1100_register_uart(2, 1); -#endif /* set some GPDR bits here while it's safe */ - GPDR |= GPIO_CF_RESET; -#ifdef CONFIG_SA1100_CERF_CPLD - GPDR |= GPIO_PWR_SHUTDOWN; -#endif + GPDR |= CERF_GPIO_CF_RESET; } -MACHINE_START(CERF, "Intrinsyc's Cerf Family of Products") +static int __init cerf_init(void) +{ + int ret; + + if (!machine_is_cerf()) + return -ENODEV; + + ret = platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); + if (ret < 0) + return ret; + + return 0; +} + +arch_initcall(cerf_init); + +MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") MAINTAINER("support@intrinsyc.com") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(cerf_map_io) diff -urN linux-2.6.2-rc2/arch/arm/mach-sa1100/generic.c linux-2.6.2-rc3/arch/arm/mach-sa1100/generic.c --- linux-2.6.2-rc2/arch/arm/mach-sa1100/generic.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/arm/mach-sa1100/generic.c 2004-01-30 18:49:19.000000000 -0800 @@ -99,6 +99,7 @@ { return cclk_frequency_100khz[PPCR & 0xf] * 100; } +EXPORT_SYMBOL(sa11x0_getspeed); #else /* * We still need to provide this so building without cpufreq works. diff -urN linux-2.6.2-rc2/arch/i386/boot/setup.S linux-2.6.2-rc3/arch/i386/boot/setup.S --- linux-2.6.2-rc2/arch/i386/boot/setup.S 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/boot/setup.S 2004-01-30 18:49:19.000000000 -0800 @@ -307,7 +307,7 @@ # a whole bunch of different types, and allows memory holes and # everything. We scan through this memory map and build a list # of the first 32 memory areas, which we return at [E820MAP]. -# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm +# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. #define SMAP 0x534d4150 diff -urN linux-2.6.2-rc2/arch/i386/kernel/acpi/boot.c linux-2.6.2-rc3/arch/i386/kernel/acpi/boot.c --- linux-2.6.2-rc2/arch/i386/kernel/acpi/boot.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/acpi/boot.c 2004-01-30 18:49:19.000000000 -0800 @@ -41,9 +41,8 @@ #define PREFIX "ACPI: " -extern int acpi_disabled; -extern int acpi_irq; -extern int acpi_ht; +int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ +int acpi_ht __initdata = 1; /* enable HT */ int acpi_lapic = 0; int acpi_ioapic = 0; @@ -250,29 +249,66 @@ #ifdef CONFIG_ACPI_BUS /* - * Set specified PIC IRQ to level triggered mode. + * "acpi_pic_sci=level" (current default) + * programs the PIC-mode SCI to Level Trigger. + * (NO-OP if the BIOS set Level Trigger already) + * + * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's + * it may require Edge Trigger -- use "acpi_pic_sci=edge" + * (NO-OP if the BIOS set Edge Trigger already) * * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) - * - * As the BIOS should have done this for us, - * print a warning if the IRQ wasn't already set to level. */ -void acpi_pic_set_level_irq(unsigned int irq) +static int __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */ + +void __init +acpi_pic_sci_set_trigger(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); unsigned char val = inb(port); + + printk(PREFIX "IRQ%d SCI:", irq); if (!(val & mask)) { - printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, " - "setting to Level Triggerd\n", irq); - outb(val | mask, port); + printk(" Edge"); + + if (!acpi_pic_sci_trigger) { + printk(" set to Level"); + outb(val | mask, port); + } + } else { + printk(" Level"); + + if (acpi_pic_sci_trigger) { + printk(" set to Edge"); + outb(val | mask, port); + } + } + printk(" Trigger.\n"); +} + +int __init +acpi_pic_sci_setup(char *str) +{ + while (str && *str) { + if (strncmp(str, "level", 5) == 0) + acpi_pic_sci_trigger = 0; /* force level trigger */ + if (strncmp(str, "edge", 4) == 0) + acpi_pic_sci_trigger = 1; /* force edge trigger */ + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); } + return 1; } + +__setup("acpi_pic_sci=", acpi_pic_sci_setup); + #endif /* CONFIG_ACPI_BUS */ @@ -387,8 +423,10 @@ * Initialize the ACPI boot-time table parser. */ result = acpi_table_init(); - if (result) + if (result) { + acpi_disabled = 1; return result; + } result = acpi_blacklisted(); if (result) { @@ -469,7 +507,7 @@ * If MPS is present, it will handle them, * otherwise the system will stay in PIC mode */ - if (acpi_disabled || !acpi_irq) { + if (acpi_disabled || acpi_noirq) { return 1; } @@ -511,6 +549,8 @@ acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_balance_set(NULL); + acpi_ioapic = 1; #endif /* CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER */ diff -urN linux-2.6.2-rc2/arch/i386/kernel/apm.c linux-2.6.2-rc3/arch/i386/kernel/apm.c --- linux-2.6.2-rc2/arch/i386/kernel/apm.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/apm.c 2004-01-30 18:49:19.000000000 -0800 @@ -1201,6 +1201,7 @@ } device_suspend(3); + device_power_down(3); /* serialize with the timer interrupt */ write_seqlock_irq(&xtime_lock); @@ -1234,6 +1235,7 @@ if (err != APM_SUCCESS) apm_error("suspend", err); err = (err == APM_SUCCESS) ? 0 : -EIO; + device_power_up(); device_resume(); pm_send_all(PM_RESUME, (void *)0); queue_event(APM_NORMAL_RESUME, NULL); @@ -1252,6 +1254,7 @@ { int err; + device_power_down(3); /* serialize with the timer interrupt */ write_seqlock_irq(&xtime_lock); /* If needed, notify drivers here */ @@ -1261,6 +1264,7 @@ err = set_system_power_state(APM_STATE_STANDBY); if ((err != APM_SUCCESS) && (err != APM_NO_ERROR)) apm_error("standby", err); + device_power_up(); } static apm_event_t get_event(void) diff -urN linux-2.6.2-rc2/arch/i386/kernel/cpu/cpufreq/acpi.c linux-2.6.2-rc3/arch/i386/kernel/cpu/cpufreq/acpi.c --- linux-2.6.2-rc2/arch/i386/kernel/cpu/cpufreq/acpi.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/cpu/cpufreq/acpi.c 2004-01-30 18:49:19.000000000 -0800 @@ -108,7 +108,7 @@ } perf->control_register = (u16) reg->address; - + perf->control_register_bit_width = reg->bit_width; /* * status_register */ @@ -135,6 +135,7 @@ } perf->status_register = (u16) reg->address; + perf->status_register_bit_width = reg->bit_width; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "control_register[0x%04x] status_register[0x%04x]\n", @@ -207,6 +208,12 @@ goto end; } + if (!px->core_frequency) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n")); + result = -EFAULT; + goto end; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", i, @@ -224,6 +231,42 @@ return_VALUE(result); } +static int +acpi_processor_write_port( + u16 port, + u8 bit_width, + u32 value) +{ + if (bit_width <= 8) { + outb(value, port); + } else if (bit_width <= 16) { + outw(value, port); + } else if (bit_width <= 32) { + outl(value, port); + } else { + return -ENODEV; + } + return 0; +} + +static int +acpi_processor_read_port( + u16 port, + u8 bit_width, + u32 *ret) +{ + *ret = 0; + if (bit_width <= 8) { + *ret = inb(port); + } else if (bit_width <= 16) { + *ret = inw(port); + } else if (bit_width <= 32) { + *ret = inl(port); + } else { + return -ENODEV; + } + return 0; +} static int acpi_processor_set_performance ( @@ -231,7 +274,9 @@ int state) { u16 port = 0; - u16 value = 0; + u8 bit_width = 0; + int ret = 0; + u32 value = 0; int i = 0; struct cpufreq_freqs cpufreq_freqs; @@ -279,12 +324,18 @@ */ port = perf->control_register; - value = (u16) perf->states[state].control; + bit_width = perf->control_register_bit_width; + value = (u32) perf->states[state].control; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Writing 0x%04x to port 0x%04x\n", value, port)); + "Writing 0x%08x to port 0x%04x\n", value, port)); - outw(value, port); + ret = acpi_processor_write_port(port, bit_width, value); + if (ret) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Invalid port width 0x%04x\n", bit_width)); + return_VALUE(ret); + } /* * Then we read the 'status_register' and compare the value with the @@ -294,14 +345,20 @@ */ port = perf->status_register; + bit_width = perf->status_register_bit_width; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Looking for 0x%04x from port 0x%04x\n", - (u16) perf->states[state].status, port)); + "Looking for 0x%08x from port 0x%04x\n", + (u32) perf->states[state].status, port)); for (i=0; i<100; i++) { - value = inw(port); - if (value == (u16) perf->states[state].status) + ret = acpi_processor_read_port(port, bit_width, &value); + if (ret) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Invalid port width 0x%04x\n", bit_width)); + return_VALUE(ret); + } + if (value == (u32) perf->states[state].status) break; udelay(10); } @@ -309,7 +366,7 @@ /* notify cpufreq */ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); - if (value != (u16) perf->states[state].status) { + if (value != (u32) perf->states[state].status) { unsigned int tmp = cpufreq_freqs.new; cpufreq_freqs.new = cpufreq_freqs.old; cpufreq_freqs.old = tmp; diff -urN linux-2.6.2-rc2/arch/i386/kernel/dmi_scan.c linux-2.6.2-rc3/arch/i386/kernel/dmi_scan.c --- linux-2.6.2-rc2/arch/i386/kernel/dmi_scan.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/dmi_scan.c 2004-01-30 18:49:19.000000000 -0800 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ int is_sony_vaio_laptop; int is_unsafe_smbus; +int es7000_plat = 0; struct dmi_header { @@ -520,6 +522,7 @@ } +#ifdef CONFIG_ACPI_BOOT extern int acpi_disabled, acpi_force; static __init __attribute__((unused)) int acpi_disable(struct dmi_blacklist *d) @@ -534,8 +537,6 @@ return 0; } - -#ifdef CONFIG_ACPI_BOOT extern int acpi_ht; /* @@ -558,10 +559,8 @@ #ifdef CONFIG_ACPI_PCI static __init int disable_acpi_pci(struct dmi_blacklist *d) { - extern __init void pci_disable_acpi(void) ; - printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident); - pci_disable_acpi(); + acpi_noirq_set(); return 0; } #endif @@ -1065,6 +1064,7 @@ printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s); printk(KERN_NOTICE "You can enable it with acpi=force\n"); acpi_disabled = 1; + acpi_ht = 0; } } } diff -urN linux-2.6.2-rc2/arch/i386/kernel/io_apic.c linux-2.6.2-rc3/arch/i386/kernel/io_apic.c --- linux-2.6.2-rc2/arch/i386/kernel/io_apic.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/io_apic.c 2004-01-30 18:49:19.000000000 -0800 @@ -1650,10 +1650,6 @@ unsigned char old_id; unsigned long flags; - if (acpi_ioapic) - /* This gets done during IOAPIC enumeration for ACPI. */ - return; - /* * This is broken; anything with a real cpu count has to * circumvent this idiocy regardless. @@ -2286,12 +2282,14 @@ /* * Set up IO-APIC IRQ routing. */ - setup_ioapic_ids_from_mpc(); + if (!acpi_ioapic) + setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - print_IO_APIC(); + if (!acpi_ioapic) + print_IO_APIC(); } /* diff -urN linux-2.6.2-rc2/arch/i386/kernel/mpparse.c linux-2.6.2-rc3/arch/i386/kernel/mpparse.c --- linux-2.6.2-rc2/arch/i386/kernel/mpparse.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/mpparse.c 2004-01-30 18:49:19.000000000 -0800 @@ -1081,8 +1081,14 @@ ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; + /* + * MPS INTI flags: + * trigger: 0=default, 1=edge, 3=level + * polarity: 0=default, 1=high, 3=low + * Per ACPI spec, default for SCI means level/low. + */ io_apic_set_pci_routing(ioapic, ioapic_pin, irq, - (flags.trigger >> 1) , (flags.polarity >> 1)); + (flags.trigger == 1 ? 0 : 1), (flags.polarity == 1 ? 0 : 1)); } #ifdef CONFIG_ACPI_PCI @@ -1129,8 +1135,11 @@ continue; ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; - if (!ioapic && (irq < 16)) - irq += 16; + if (es7000_plat) { + if (!ioapic && (irq < 16)) + irq += 16; + } + /* * Avoid pin reprogramming. PRTs typically include entries * with redundant pin->irq mappings (but unique PCI devices); @@ -1166,6 +1175,10 @@ mp_ioapic_routing[ioapic].apic_id, ioapic_pin, entry->irq); } + + print_IO_APIC(); + + return; } #endif /*CONFIG_ACPI_PCI*/ diff -urN linux-2.6.2-rc2/arch/i386/kernel/setup.c linux-2.6.2-rc3/arch/i386/kernel/setup.c --- linux-2.6.2-rc2/arch/i386/kernel/setup.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/kernel/setup.c 2004-01-30 18:49:19.000000000 -0800 @@ -78,13 +78,10 @@ EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_ACPI_BOOT - int acpi_irq __initdata = 1; /* enable IRQ */ - int acpi_ht __initdata = 1; /* enable HT */ +extern int __initdata acpi_ht; +int __initdata acpi_force = 0; #endif -int acpi_force __initdata = 0; - - int MCA_bus; /* for MCA, but anyone else can use it if they want */ unsigned int machine_id; @@ -573,7 +570,7 @@ /* "pci=noacpi" disables ACPI interrupt routing */ else if (!memcmp(from, "pci=noacpi", 10)) { - acpi_irq = 0; + acpi_noirq_set(); } #ifdef CONFIG_X86_LOCAL_APIC diff -urN linux-2.6.2-rc2/arch/i386/mach-es7000/es7000.c linux-2.6.2-rc3/arch/i386/mach-es7000/es7000.c --- linux-2.6.2-rc2/arch/i386/mach-es7000/es7000.c 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/mach-es7000/es7000.c 2004-01-30 18:49:19.000000000 -0800 @@ -51,8 +51,6 @@ int mip_port; unsigned long mip_addr, host_addr; -static int es7000_plat; - /* * Parse the OEM Table */ diff -urN linux-2.6.2-rc2/arch/i386/pci/acpi.c linux-2.6.2-rc3/arch/i386/pci/acpi.c --- linux-2.6.2-rc2/arch/i386/pci/acpi.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/pci/acpi.c 2004-01-30 18:49:19.000000000 -0800 @@ -18,7 +18,7 @@ if (pcibios_scanned) return 0; - if (!(pci_probe & PCI_NO_ACPI_ROUTING)) { + if (!acpi_noirq) { if (!acpi_pci_irq_init()) { printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n"); @@ -31,15 +31,4 @@ return 0; } - -/* - * pci_disable_acpi() - * act like pci=noacpi seen on command line - * called by DMI blacklist code - */ -__init void pci_disable_acpi(void) -{ - pci_probe |= PCI_NO_ACPI_ROUTING; -} - subsys_initcall(pci_acpi_init); diff -urN linux-2.6.2-rc2/arch/i386/pci/common.c linux-2.6.2-rc3/arch/i386/pci/common.c --- linux-2.6.2-rc2/arch/i386/pci/common.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/pci/common.c 2004-01-30 18:49:19.000000000 -0800 @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -197,12 +198,10 @@ return NULL; } #endif -#ifdef CONFIG_ACPI_PCI else if (!strcmp(str, "noacpi")) { - pci_probe |= PCI_NO_ACPI_ROUTING; + acpi_noirq_set(); return NULL; } -#endif #ifndef CONFIG_X86_VISWS else if (!strcmp(str, "usepirqmask")) { pci_probe |= PCI_USE_PIRQ_MASK; diff -urN linux-2.6.2-rc2/arch/i386/pci/pci.h linux-2.6.2-rc3/arch/i386/pci/pci.h --- linux-2.6.2-rc2/arch/i386/pci/pci.h 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/arch/i386/pci/pci.h 2004-01-30 18:49:19.000000000 -0800 @@ -22,7 +22,6 @@ #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 #define PCI_ASSIGN_ALL_BUSSES 0x4000 -#define PCI_NO_ACPI_ROUTING 0x8000 extern unsigned int pci_probe; diff -urN linux-2.6.2-rc2/arch/ia64/Kconfig linux-2.6.2-rc3/arch/ia64/Kconfig --- linux-2.6.2-rc2/arch/ia64/Kconfig 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/Kconfig 2004-01-30 18:49:19.000000000 -0800 @@ -16,10 +16,11 @@ The Itanium Processor Family is Intel's 64-bit successor to the 32-bit X86 line. The IA-64 Linux project has a home page at and a mailing list at - linux-ia64@linuxia64.org. + linux-ia64@vger.kernel.org. config 64BIT - def_bool y + bool + default y config MMU bool @@ -38,13 +39,13 @@ default y choice - prompt "IA-64 processor type" + prompt "Processor type" default ITANIUM config ITANIUM bool "Itanium" help - Select your IA-64 processor type. The default is Intel Itanium. + Select your IA-64 processor type. The default is Itanium. This choice is safe for all IA-64 systems, but may not perform optimally on systems with, say, Itanium 2 or newer processors. @@ -56,7 +57,7 @@ endchoice choice - prompt "IA-64 system type" + prompt "System type" default IA64_GENERIC config IA64_GENERIC @@ -65,17 +66,16 @@ select ACPI_NUMA select VIRTUAL_MEM_MAP select DISCONTIGMEM - ---help--- + help This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure a kernel for your specific system, it will be faster and smaller. - DIG-compliant For DIG ("Developer's Interface Guide") compliant - systems - HP-zx1 For HP systems + generic For any supported IA-64 system + DIG-compliant For DIG ("Developer's Interface Guide") compliant systems + HP-zx1/sx1000 For HP systems SGI-SN2 For SGI Altix systems - Ski-simulator For the HP simulator - () + Ski-simulator For the HP simulator () If you don't know what to do, choose "generic". @@ -83,11 +83,10 @@ bool "DIG-compliant" config IA64_HP_ZX1 - bool "HP-zx1" + bool "HP-zx1/sx1000" help - Build a kernel that runs on HP zx1-based systems. This adds support - for the zx1 I/O MMU and makes root bus bridges appear in PCI config - space (required for zx1 agpgart support). + Build a kernel that runs on HP zx1 and sx1000 systems. This adds + support for the HP I/O MMU. config IA64_SGI_SN2 bool "SGI-SN2" @@ -103,7 +102,7 @@ config IA64_PAGE_SIZE_4KB bool "4KB" - ---help--- + help This lets you select the page size of the kernel. For best IA-64 performance, a page size of 8KB or 16KB is recommended. For best IA-32 compatibility, a page size of 4KB should be selected (the vast @@ -134,7 +133,7 @@ bool depends on !IA64_HP_SIM default y - ---help--- + help ACPI/OSPM support for Linux is currently under development. As such, this support is preliminary and EXPERIMENTAL. Configuring ACPI support enables kernel interfaces that allow higher level software @@ -182,7 +181,7 @@ default y config ITANIUM_BSTEP_SPECIFIC - bool "Enable Itanium B-step specific code" + bool "Itanium B-step specific code" depends on ITANIUM help Select this option to build a kernel for an Itanium prototype system @@ -197,38 +196,30 @@ # align cache-sensitive data to 64 bytes config MCKINLEY_ASTEP_SPECIFIC - bool "Enable McKinley A-step specific code" + bool "McKinley A-step specific code" depends on MCKINLEY help Select this option to build a kernel for an IA-64 McKinley prototype system with any A-stepping CPU. config MCKINLEY_A0_SPECIFIC - bool "Enable McKinley A0/A1-step specific code" + bool "McKinley A0/A1-step specific code" depends on MCKINLEY_ASTEP_SPECIFIC help Select this option to build a kernel for an IA-64 McKinley prototype system with an A0 or A1 stepping CPU. config NUMA - bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 - default y if IA64_SGI_SN2 || IA64_GENERIC + bool "NUMA support" + depends on !IA64_HP_SIM + default y if IA64_SGI_SN2 help Say Y to compile the kernel to support NUMA (Non-Uniform Memory Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. -config DISCONTIGMEM - bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP - default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA - help - Say Y to support efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. - config VIRTUAL_MEM_MAP - bool "Enable Virtual Mem Map" + bool "Virtual mem map" default y if !IA64_HP_SIM help Say Y to compile the kernel with support for a virtual mem map. @@ -237,8 +228,18 @@ require the DISCONTIGMEM option for your machine. If you are unsure, say Y. +config DISCONTIGMEM + bool "Discontiguous memory support" + depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP + default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA + help + Say Y to support efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See for more. + config IA64_MCA - bool "Enable IA-64 Machine Check Abort" + bool "Machine Check Abort" default y if !IA64_HP_SIM help Say Y here to enable machine check support for IA-64. If you're @@ -248,7 +249,7 @@ bool "Power Management support" depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 default y - ---help--- + help "Power Management" means that parts of your computer are shut off or put into a power conserving "sleep" mode if they are not being used. There are two competing standards for doing this: APM @@ -257,8 +258,7 @@ Power Management is most important for battery powered laptop computers; if you have a laptop, check out the Linux Laptop home - page on the WWW at - and the + page on the WWW at and the Battery Powered Linux mini-HOWTO, available from . @@ -268,11 +268,11 @@ config IOSAPIC bool - depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2 + depends on !IA64_HP_SIM default y config IA64_SGI_SN_SIM - bool "Enable SGI Medusa Simulator Support" + bool "SGI Medusa Simulator Support" depends on IA64_SGI_SN2 help If you are compiling a kernel that will run under SGI's IA-64 @@ -283,7 +283,7 @@ default "18" choice - prompt "IA-64 Huge TLB Page Size" + prompt "Huge TLB page size" depends on HUGETLB_PAGE default HUGETLB_PAGE_SIZE_16MB @@ -317,7 +317,7 @@ config IA64_PAL_IDLE bool "Use PAL_HALT_LIGHT in idle loop" - ---help--- + help Say Y here to enable use of PAL_HALT_LIGHT in the cpu_idle loop. This allows the CPU to enter a low power state when idle. You can enable CONFIG_IA64_PALINFO and check /proc/pal/cpu0/power_info @@ -325,24 +325,35 @@ unsure your firmware supports it, answer N. config SMP - bool "SMP support" - ---help--- + bool "Symmetric multi-processing support" + help This enables support for systems with more than one CPU. If you have - a system with only one CPU say N. If you have a system with more than - one CPU, say Y. + a system with only one CPU, say N. If you have a system with more + than one CPU, say Y. If you say N here, the kernel will run on single and multiprocessor - systems, but will use only one CPU of a multiprocessor system. If + systems, but will use only one CPU of a multiprocessor system. If you say Y here, the kernel will run on many, but not all, - singleprocessor system. On a singleprocessor system, the kernel + single processor systems. On a single processor system, the kernel will run faster if you say N here. - See also the , - , and the SMP-HOWTO available at - . + See also the and the SMP-HOWTO + available at . If you don't know what to do here, say N. +config NR_CPUS + int "Maximum number of CPUs (2-512)" + range 2 512 + depends on SMP + default "64" + help + You should set this to the number of CPUs in your system, but + keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but + only use 2 CPUs on a >2 CPU system. Setting this to a value larger + than 64 will cause the use of a CPU mask array, causing a small + performance hit. + config PREEMPT bool "Preemptible Kernel" help @@ -355,8 +366,13 @@ Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. +config HAVE_DEC_LOCK + bool + depends on (SMP || PREEMPT) + default y + config IA32_SUPPORT - bool "Support running of Linux/x86 binaries" + bool "Support for Linux/x86 binaries" help IA-64 processors can execute IA-32 (X86) instructions. By saying Y here, the kernel will include IA-32 system call @@ -369,11 +385,6 @@ depends on IA32_SUPPORT default y -config HAVE_DEC_LOCK - bool - depends on (SMP || PREEMPT) - default y - config PERFMON bool "Performance monitor support" help @@ -393,7 +404,6 @@ To use this option, you have to ensure that the "/proc file system support" (CONFIG_PROC_FS) is enabled, too. - config EFI_VARS tristate "/proc/efi/vars support" help @@ -404,18 +414,6 @@ To use this option, you have to check that the "/proc file system support" (CONFIG_PROC_FS) is enabled, too. -config NR_CPUS - int "Maximum number of CPUs (2-512)" - range 2 512 - depends on SMP - default "64" - help - You should set this to the number of CPUs in your system, but - keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but - only use 2 CPUs on a >2 CPU system. Setting this to a value larger - than 64 will cause the use of a CPU mask array, causing a small - performance hit. - source "fs/Kconfig.binfmt" if !IA64_HP_SIM @@ -443,7 +441,7 @@ config HOTPLUG bool "Support for hot-pluggable devices" - ---help--- + help Say Y here if you want to plug devices into your computer while the system is running, and be able to use them quickly. In many cases, the devices can likewise be unplugged at any time too. @@ -510,6 +508,8 @@ source "drivers/char/Kconfig" +source "drivers/i2c/Kconfig" + #source drivers/misc/Config.in source "drivers/media/Kconfig" diff -urN linux-2.6.2-rc2/arch/ia64/hp/common/sba_iommu.c linux-2.6.2-rc3/arch/ia64/hp/common/sba_iommu.c --- linux-2.6.2-rc2/arch/ia64/hp/common/sba_iommu.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/hp/common/sba_iommu.c 2004-01-30 18:49:19.000000000 -0800 @@ -158,6 +158,10 @@ #define IOC_TCNFG 0x318 #define IOC_PDIR_BASE 0x320 +#define IOC_ROPE0_CFG 0x500 +#define IOC_ROPE_AO 0x10 /* Allow "Relaxed Ordering" */ + + /* AGP GART driver looks for this */ #define ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL @@ -1361,6 +1365,7 @@ #ifdef FULL_VALID_PDIR unsigned long index; #endif + unsigned int i; /* ** Firmware programs the base and size of a "safe IOVA space" @@ -1455,6 +1460,18 @@ /* Enable IOVA translation */ WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE); READ_REG(ioc->ioc_hpa + IOC_IBASE); + + /* Clear ROPE(N)_CONFIG AO bit. + ** Disables "NT Ordering" (~= !"Relaxed Ordering") + ** Overrides bit 1 in DMA Hint Sets. + ** Improves netperf UDP_STREAM by ~10% for tg3 on bcm5701. + */ + for (i=0; i<(8*8); i+=8) { + unsigned long rope_config; + rope_config = READ_REG(ioc->ioc_hpa + IOC_ROPE0_CFG + i); + rope_config &= ~IOC_ROPE_AO; + WRITE_REG(rope_config, ioc->ioc_hpa + IOC_ROPE0_CFG + i); + } } static void __init diff -urN linux-2.6.2-rc2/arch/ia64/kernel/entry.S linux-2.6.2-rc3/arch/ia64/kernel/entry.S --- linux-2.6.2-rc2/arch/ia64/kernel/entry.S 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/kernel/entry.S 2004-01-30 18:49:19.000000000 -0800 @@ -489,18 +489,35 @@ * because some system calls (such as ia64_execve) directly * manipulate ar.pfs. */ - .global ia64_strace_leave_kernel - GLOBAL_ENTRY(ia64_trace_syscall) PT_REGS_UNWIND_INFO(0) -{ /* - * Some versions of gas generate bad unwind info if the first instruction of a - * procedure doesn't go into the first slot of a bundle. This is a workaround. + /* + * We need to preserve the scratch registers f6-f11 in case the system + * call is sigreturn. */ - nop.m 0 - nop.i 0 + adds r16=PT(F6)+16,sp + adds r17=PT(F7)+16,sp + ;; + stf.spill [r16]=f6,32 + stf.spill [r17]=f7,32 + ;; + stf.spill [r16]=f8,32 + stf.spill [r17]=f9,32 + ;; + stf.spill [r16]=f10 + stf.spill [r17]=f11 br.call.sptk.many rp=syscall_trace // give parent a chance to catch syscall args -} + adds r16=PT(F6)+16,sp + adds r17=PT(F7)+16,sp + ;; + ldf.fill f6=[r16],32 + ldf.fill f7=[r17],32 + ;; + ldf.fill f8=[r16],32 + ldf.fill f9=[r17],32 + ;; + ldf.fill f10=[r16] + ldf.fill f11=[r17] // the syscall number may have changed, so re-load it and re-calculate the // syscall entry-point: adds r15=PT(R15)+16,sp // r15 = &pt_regs.r15 (syscall #) @@ -529,9 +546,8 @@ .strace_save_retval: .mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8 .mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10 -ia64_strace_leave_kernel: br.call.sptk.many rp=syscall_trace // give parent a chance to catch return value -.rety: br.cond.sptk ia64_leave_syscall +.ret3: br.cond.sptk ia64_leave_syscall strace_error: ld8 r3=[r2] // load pt_regs.r8 @@ -545,6 +561,23 @@ br.cond.sptk .strace_save_retval END(ia64_trace_syscall) + /* + * When traced and returning from sigreturn, we invoke syscall_trace but then + * go straight to ia64_leave_kernel rather than ia64_leave_syscall. + */ +GLOBAL_ENTRY(ia64_strace_leave_kernel) + PT_REGS_UNWIND_INFO(0) +{ /* + * Some versions of gas generate bad unwind info if the first instruction of a + * procedure doesn't go into the first slot of a bundle. This is a workaround. + */ + nop.m 0 + nop.i 0 + br.call.sptk.many rp=syscall_trace // give parent a chance to catch return value +} +.ret4: br.cond.sptk ia64_leave_kernel +END(ia64_strace_leave_kernel) + GLOBAL_ENTRY(ia64_ret_from_clone) PT_REGS_UNWIND_INFO(0) { /* diff -urN linux-2.6.2-rc2/arch/ia64/kernel/ia64_ksyms.c linux-2.6.2-rc3/arch/ia64/kernel/ia64_ksyms.c --- linux-2.6.2-rc2/arch/ia64/kernel/ia64_ksyms.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/kernel/ia64_ksyms.c 2004-01-30 18:49:19.000000000 -0800 @@ -103,20 +103,22 @@ #include EXPORT_SYMBOL(unw_init_running); -#ifdef CONFIG_SMP -# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +#ifdef ASM_SUPPORTED +# ifdef CONFIG_SMP +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) /* * This is not a normal routine and we don't want a function descriptor for it, so we use * a fake declaration here. */ extern char ia64_spinlock_contention_pre3_4; EXPORT_SYMBOL(ia64_spinlock_contention_pre3_4); -# else +# else /* * This is not a normal routine and we don't want a function descriptor for it, so we use * a fake declaration here. */ extern char ia64_spinlock_contention; EXPORT_SYMBOL(ia64_spinlock_contention); +# endif # endif #endif diff -urN linux-2.6.2-rc2/arch/ia64/kernel/irq_lsapic.c linux-2.6.2-rc3/arch/ia64/kernel/irq_lsapic.c --- linux-2.6.2-rc2/arch/ia64/kernel/irq_lsapic.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/kernel/irq_lsapic.c 2004-01-30 18:49:19.000000000 -0800 @@ -33,6 +33,5 @@ .enable = lsapic_noop, .disable = lsapic_noop, .ack = lsapic_noop, - .end = lsapic_noop, - .set_affinity = (void (*)(unsigned int, unsigned long)) lsapic_noop + .end = lsapic_noop }; diff -urN linux-2.6.2-rc2/arch/ia64/kernel/smpboot.c linux-2.6.2-rc3/arch/ia64/kernel/smpboot.c --- linux-2.6.2-rc2/arch/ia64/kernel/smpboot.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/kernel/smpboot.c 2004-01-30 18:49:19.000000000 -0800 @@ -467,10 +467,10 @@ #ifdef CONFIG_NUMA /* on which node is each logical CPU (one cacheline even for 64 CPUs) */ -volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; +u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; EXPORT_SYMBOL(cpu_to_node_map); /* which logical CPUs are on which nodes */ -volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; +cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; /* * Build cpu to node mapping and initialize the per node cpu masks. @@ -566,8 +566,8 @@ if (cpu_online(cpu)) bogosum += cpu_data(cpu)->loops_per_jiffy; - printk(KERN_INFO "Total of %lu processors activated (%lu.%02lu BogoMIPS).\n", - num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); + printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", + (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); } int __devinit diff -urN linux-2.6.2-rc2/arch/ia64/kernel/time.c linux-2.6.2-rc3/arch/ia64/kernel/time.c --- linux-2.6.2-rc2/arch/ia64/kernel/time.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/kernel/time.c 2004-01-30 18:49:19.000000000 -0800 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -243,6 +244,8 @@ { unsigned long new_itm; + platform_timer_interrupt(irq, dev_id, regs); + new_itm = local_cpu_data->itm_next; if (!time_after(ia64_get_itc(), new_itm)) diff -urN linux-2.6.2-rc2/arch/ia64/kernel/unaligned.c linux-2.6.2-rc3/arch/ia64/kernel/unaligned.c --- linux-2.6.2-rc2/arch/ia64/kernel/unaligned.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/kernel/unaligned.c 2004-01-30 18:49:19.000000000 -0800 @@ -1,7 +1,7 @@ /* * Architecture-specific unaligned trap handling. * - * Copyright (C) 1999-2002 Hewlett-Packard Co + * Copyright (C) 1999-2002, 2004 Hewlett-Packard Co * Stephane Eranian * David Mosberger-Tang * @@ -1328,7 +1328,7 @@ * handler into reading an arbitrary kernel addresses... */ if (!user_mode(regs)) - eh = SEARCH_EXCEPTION_TABLE(regs); + eh = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); if (user_mode(regs) || eh) { if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) goto force_sigbus; diff -urN linux-2.6.2-rc2/arch/ia64/mm/extable.c linux-2.6.2-rc3/arch/ia64/mm/extable.c --- linux-2.6.2-rc2/arch/ia64/mm/extable.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/mm/extable.c 2004-01-30 18:49:19.000000000 -0800 @@ -1,7 +1,7 @@ /* * Kernel exception handling table support. Derived from arch/alpha/mm/extable.c. * - * Copyright (C) 1998, 1999, 2001-2002 Hewlett-Packard Co + * Copyright (C) 1998, 1999, 2001-2002, 2004 Hewlett-Packard Co * David Mosberger-Tang */ @@ -10,9 +10,51 @@ #include #include -void sort_extable(struct exception_table_entry *start, - struct exception_table_entry *finish) +static inline int +compare_entries (struct exception_table_entry *l, struct exception_table_entry *r) { + u64 lip = (u64) &l->addr + l->addr; + u64 rip = (u64) &r->addr + r->addr; + + if (lip < rip) + return -1; + if (lip == rip) + return 0; + else + return 1; +} + +static inline void +swap_entries (struct exception_table_entry *l, struct exception_table_entry *r) +{ + u64 delta = (u64) r - (u64) l; + struct exception_table_entry tmp; + + tmp = *l; + l->addr = r->addr + delta; + l->cont = r->cont + delta; + r->addr = tmp.addr - delta; + r->cont = tmp.cont - delta; +} + +/* + * Sort the exception table. It's usually already sorted, but there may be unordered + * entries due to multiple text sections (such as the .init text section). Note that the + * exception-table-entries contain location-relative addresses, which requires a bit of + * care during sorting to avoid overflows in the offset members (e.g., it would not be + * safe to make a temporary copy of an exception-table entry on the stack, because the + * stack may be more than 2GB away from the exception-table). + */ +void +sort_extable (struct exception_table_entry *start, struct exception_table_entry *finish) +{ + struct exception_table_entry *p, *q; + + /* insertion sort */ + for (p = start + 1; p < finish; ++p) + /* start .. p-1 is sorted; push p down to it's proper place */ + for (q = p; q > start && compare_entries(&q[0], &q[-1]) < 0; --q) + swap_entries(&q[0], &q[-1]); } const struct exception_table_entry * diff -urN linux-2.6.2-rc2/arch/ia64/mm/fault.c linux-2.6.2-rc3/arch/ia64/mm/fault.c --- linux-2.6.2-rc2/arch/ia64/mm/fault.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/mm/fault.c 2004-01-30 18:49:19.000000000 -0800 @@ -58,7 +58,7 @@ if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0; - pmd = pmd_offset(pgd,address); + pmd = pmd_offset(pgd, address); if (pmd_none(*pmd) || pmd_bad(*pmd)) return 0; diff -urN linux-2.6.2-rc2/arch/ia64/sn/io/sn2/xbow.c linux-2.6.2-rc3/arch/ia64/sn/io/sn2/xbow.c --- linux-2.6.2-rc2/arch/ia64/sn/io/sn2/xbow.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/sn/io/sn2/xbow.c 2004-01-30 18:49:19.000000000 -0800 @@ -153,7 +153,7 @@ #if DEBUG && ATTACH_DEBUG char name[MAXDEVNAME]; #endif - static void xbow_errintr_handler(int, void *, struct pt_regs *); + static irqreturn_t xbow_errintr_handler(int, void *, struct pt_regs *); #if DEBUG && ATTACH_DEBUG diff -urN linux-2.6.2-rc2/arch/ia64/sn/kernel/sn2/Makefile linux-2.6.2-rc3/arch/ia64/sn/kernel/sn2/Makefile --- linux-2.6.2-rc2/arch/ia64/sn/kernel/sn2/Makefile 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/sn/kernel/sn2/Makefile 2004-01-30 18:49:19.000000000 -0800 @@ -10,4 +10,4 @@ # obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ - prominfo_proc.o timer.o + prominfo_proc.o timer.o timer_interrupt.o diff -urN linux-2.6.2-rc2/arch/ia64/sn/kernel/sn2/sn2_smp.c linux-2.6.2-rc3/arch/ia64/sn/kernel/sn2/sn2_smp.c --- linux-2.6.2-rc2/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-01-30 18:49:19.000000000 -0800 @@ -50,7 +50,7 @@ piows = pda->pio_write_status_addr; do { - __asm__ __volatile__ ("mf.a" ::: "memory"); + ia64_mfa(); } while (((ws = *piows) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK); return ws; @@ -93,7 +93,8 @@ if (is_headless_node(cnode)) continue; if (cnode == mycnode) { - asm volatile ("ptc.ga %0,%1;;srlz.i;;" :: "r"(start), "r"(nbits<<2) : "memory"); + ia64_ptcga(start, nbits<<2); + ia64_srlz_i(); } else { nasid = cnodeid_to_nasid(cnode); ptc0 = CHANGE_NASID(nasid, ptc0); diff -urN linux-2.6.2-rc2/arch/ia64/sn/kernel/sn2/timer_interrupt.c linux-2.6.2-rc3/arch/ia64/sn/kernel/sn2/timer_interrupt.c --- linux-2.6.2-rc2/arch/ia64/sn/kernel/sn2/timer_interrupt.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/arch/ia64/sn/kernel/sn2/timer_interrupt.c 2004-01-30 18:49:19.000000000 -0800 @@ -0,0 +1,63 @@ +/* + * + * + * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ + +#include +#include +#include + +extern void sn_lb_int_war_check(void); +extern irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs); + +#define SN_LB_INT_WAR_INTERVAL 100 + +void +sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* LED blinking */ + if (!pda->hb_count--) { + pda->hb_count = HZ/2; + set_led_bits(pda->hb_state ^= LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT); + } + + if (enable_shub_wars_1_1()) { + /* Bugfix code for SHUB 1.1 */ + if (pda->pio_shub_war_cam_addr) + *pda->pio_shub_war_cam_addr = 0x8000000000000010UL; + } + if (pda->sn_lb_int_war_ticks == 0) + sn_lb_int_war_check(); + pda->sn_lb_int_war_ticks++; + if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL) + pda->sn_lb_int_war_ticks = 0; +} diff -urN linux-2.6.2-rc2/arch/sparc64/kernel/head.S linux-2.6.2-rc3/arch/sparc64/kernel/head.S --- linux-2.6.2-rc2/arch/sparc64/kernel/head.S 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/sparc64/kernel/head.S 2004-01-30 18:49:19.000000000 -0800 @@ -57,8 +57,9 @@ /* History: * - * 0x0202 : Supports kernel params string * 0x0300 : Supports being located at other than 0x4000 + * 0x0202 : Supports kernel params string + * 0x0201 : Supports reboot_command */ .half 0x0300 /* HdrS version */ diff -urN linux-2.6.2-rc2/arch/sparc64/kernel/power.c linux-2.6.2-rc3/arch/sparc64/kernel/power.c --- linux-2.6.2-rc2/arch/sparc64/kernel/power.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/arch/sparc64/kernel/power.c 2004-01-30 18:49:19.000000000 -0800 @@ -69,18 +69,26 @@ { static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; char *argv[] = { "/sbin/shutdown", "-h", "now", NULL }; + DECLARE_WAITQUEUE(wait, current); daemonize("powerd"); + add_wait_queue(&powerd_wait, &wait); again: - while (button_pressed == 0) { + for (;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + if (button_pressed) + break; flush_signals(current); - interruptible_sleep_on(&powerd_wait); + schedule(); } + __set_current_state(TASK_RUNNING); + remove_wait_queue(&powerd_wait, &wait); /* Ok, down we go... */ if (execve("/sbin/shutdown", argv, envp) < 0) { printk("powerd: shutdown execution failed\n"); + add_wait_queue(&powerd_wait, &wait); button_pressed = 0; goto again; } diff -urN linux-2.6.2-rc2/arch/sparc64/kernel/setup.c linux-2.6.2-rc3/arch/sparc64/kernel/setup.c --- linux-2.6.2-rc2/arch/sparc64/kernel/setup.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/arch/sparc64/kernel/setup.c 2004-01-30 18:49:19.000000000 -0800 @@ -45,6 +45,7 @@ #include #include #include +#include #ifdef CONFIG_IP_PNP #include @@ -522,6 +523,22 @@ } pfn_base = phys_base >> PAGE_SHIFT; + switch (tlb_type) { + default: + case spitfire: + kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent()); + kern_base &= _PAGE_PADDR_SF; + break; + + case cheetah: + case cheetah_plus: + kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent()); + kern_base &= _PAGE_PADDR; + break; + }; + + kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; + if (!root_flags) root_mountflags &= ~MS_RDONLY; ROOT_DEV = old_decode_dev(root_dev); diff -urN linux-2.6.2-rc2/arch/sparc64/mm/init.c linux-2.6.2-rc3/arch/sparc64/mm/init.c --- linux-2.6.2-rc2/arch/sparc64/mm/init.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/sparc64/mm/init.c 2004-01-30 18:49:19.000000000 -0800 @@ -47,8 +47,19 @@ /* Ugly, but necessary... -DaveM */ unsigned long phys_base; +unsigned long kern_base; +unsigned long kern_size; unsigned long pfn_base; +/* This is even uglier. We have a problem where the kernel may not be + * located at phys_base. However, initial __alloc_bootmem() calls need to + * be adjusted to be within the 4-8Megs that the kernel is mapped to, else + * those page mappings wont work. Things are ok after inherit_prom_mappings + * is called though. Dave says he'll clean this up some other time. + * -- BenC + */ +static unsigned long bootmap_base; + /* get_new_mmu_context() uses "cache + 1". */ spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED; unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; @@ -433,7 +444,7 @@ n += 5 * sizeof(struct linux_prom_translation); for (tsz = 1; tsz < n; tsz <<= 1) /* empty */; - trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, 0UL); + trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base); if (trans == NULL) { prom_printf("inherit_prom_mappings: Cannot alloc translations.\n"); prom_halt(); @@ -453,7 +464,7 @@ * in inherit_locked_prom_mappings()). */ #define OBP_PMD_SIZE 2048 - prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, 0UL); + prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base); if (prompmd == NULL) early_pgtable_allocfail("pmd"); memset(prompmd, 0, OBP_PMD_SIZE); @@ -471,7 +482,7 @@ if (pmd_none(*pmdp)) { ptep = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE, - 0UL); + bootmap_base); if (ptep == NULL) early_pgtable_allocfail("pte"); memset(ptep, 0, BASE_PAGE_SIZE); @@ -1327,15 +1338,8 @@ * image. The kernel is hard mapped below PAGE_OFFSET in a * 4MB locked TLB translation. */ - start_pfn = PAGE_ALIGN((unsigned long) _end) - - ((unsigned long) KERNBASE); - - /* Adjust up to the physical address where the kernel begins. */ - start_pfn += phys_base; + start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT; - /* Now shift down to get the real physical page frame number. */ - start_pfn >>= PAGE_SHIFT; - bootmap_pfn = start_pfn; end_pfn = end_of_phys_memory >> PAGE_SHIFT; @@ -1365,11 +1369,13 @@ min_low_pfn = pfn_base; #ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("init_bootmem(spfn[%lx], bpfn[%lx], mlpfn[%lx])\n", - start_pfn, bootmap_pfn, max_low_pfn); + prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n", + min_low_pfn, bootmap_pfn, max_low_pfn); #endif bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn); + bootmap_base = bootmap_pfn << PAGE_SHIFT; + /* Now register the available physical memory with the * allocator. */ @@ -1378,8 +1384,7 @@ prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n", i, sp_banks[i].base_addr, sp_banks[i].num_bytes); #endif - free_bootmem(sp_banks[i].base_addr, - sp_banks[i].num_bytes); + free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes); } #ifdef CONFIG_BLK_DEV_INITRD @@ -1395,12 +1400,11 @@ } #endif /* Reserve the kernel text/data/bss. */ - size = (start_pfn << PAGE_SHIFT) - phys_base; #ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", phys_base, size); + prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size); #endif - reserve_bootmem(phys_base, size); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + reserve_bootmem(kern_base, kern_size); + *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT; /* Reserve the bootmem map. We do not account for it * in pages_avail because we will release that memory @@ -1429,7 +1433,7 @@ extern pmd_t swapper_pmd_dir[1024]; extern unsigned int sparc64_vpte_patchme1[1]; extern unsigned int sparc64_vpte_patchme2[1]; - unsigned long alias_base = phys_base + PAGE_OFFSET; + unsigned long alias_base = kern_base + PAGE_OFFSET; unsigned long second_alias_page = 0; unsigned long pt, flags, end_pfn, pages_avail; unsigned long shift = alias_base - ((unsigned long)KERNBASE); @@ -1449,7 +1453,7 @@ * if this were not true we wouldn't boot up to this point * anyways. */ - pt = phys_base | _PAGE_VALID | _PAGE_SZ4MB; + pt = kern_base | _PAGE_VALID | _PAGE_SZ4MB; pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W; local_irq_save(flags); if (tlb_type == spitfire) { @@ -1543,7 +1547,16 @@ } inherit_locked_prom_mappings(1); - + +#ifdef CONFIG_SUN_SERIAL + /* This does not logically belong here, but we need to call it at + * the moment we are able to use the bootmem allocator. This _has_ + * to be done after the prom_mappings above so since + * __alloc_bootmem() doesn't work correctly until then. + */ + sun_serial_setup(); +#endif + /* We only created DTLB mapping of this stuff. */ spitfire_flush_dtlb_nucleus_page(alias_base); if (second_alias_page) @@ -1714,17 +1727,15 @@ i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); i += 1; sparc64_valid_addr_bitmap = (unsigned long *) - __alloc_bootmem(i << 3, SMP_CACHE_BYTES, 0UL); + __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base); if (sparc64_valid_addr_bitmap == NULL) { prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); prom_halt(); } memset(sparc64_valid_addr_bitmap, 0, i << 3); - addr = PAGE_OFFSET + phys_base; - last = PAGE_ALIGN((unsigned long)_end) - - ((unsigned long) KERNBASE); - last += PAGE_OFFSET + phys_base; + addr = PAGE_OFFSET + kern_base; + last = PAGE_ALIGN(kern_size) + addr; while (addr < last) { set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap); addr += PAGE_SIZE; @@ -1764,7 +1775,7 @@ /* Put empty_pg_dir on pgd_quicklist */ extern pgd_t empty_pg_dir[1024]; unsigned long addr = (unsigned long)empty_pg_dir; - unsigned long alias_base = phys_base + PAGE_OFFSET - + unsigned long alias_base = kern_base + PAGE_OFFSET - (long)(KERNBASE); memset(empty_pg_dir, 0, sizeof(empty_pg_dir)); @@ -1800,7 +1811,7 @@ struct page *p; page = (addr + - ((unsigned long) __va(phys_base)) - + ((unsigned long) __va(kern_base)) - ((unsigned long) KERNBASE)); p = virt_to_page(page); diff -urN linux-2.6.2-rc2/arch/x86_64/kernel/acpi/boot.c linux-2.6.2-rc3/arch/x86_64/kernel/acpi/boot.c --- linux-2.6.2-rc2/arch/x86_64/kernel/acpi/boot.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/arch/x86_64/kernel/acpi/boot.c 2004-01-30 18:49:19.000000000 -0800 @@ -46,11 +46,13 @@ #include #include -int acpi_lapic = 0; -int acpi_ioapic = 0; - #define PREFIX "ACPI: " +int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ +int acpi_ht __initdata = 1; /* enable HT */ + +int acpi_lapic = 0; +int acpi_ioapic = 0; /* -------------------------------------------------------------------------- Boot-time Configuration @@ -253,29 +255,66 @@ #ifdef CONFIG_ACPI_BUS /* - * Set specified PIC IRQ to level triggered mode. + * "acpi_pic_sci=level" (current default) + * programs the PIC-mode SCI to Level Trigger. + * (NO-OP if the BIOS set Level Trigger already) + * + * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's + * it may require Edge Trigger -- use "acpi_pic_sci=edge" + * (NO-OP if the BIOS set Edge Trigger already) * * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) - * - * As the BIOS should have done this for us, - * print a warning if the IRQ wasn't already set to level. */ -void acpi_pic_set_level_irq(unsigned int irq) +static int __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */ + +void __init +acpi_pic_sci_set_trigger(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); unsigned char val = inb(port); + + printk(PREFIX "IRQ%d SCI:", irq); if (!(val & mask)) { - printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, " - "setting to Level Triggerd\n", irq); - outb(val | mask, port); + printk(" Edge"); + + if (!acpi_pic_sci_trigger) { + printk(" set to Level"); + outb(val | mask, port); + } + } else { + printk(" Level"); + + if (acpi_pic_sci_trigger) { + printk(" set to Edge"); + outb(val | mask, port); + } } + printk(" Trigger.\n"); } + +int __init +acpi_pic_sci_setup(char *str) +{ + while (str && *str) { + if (strncmp(str, "level", 5) == 0) + acpi_pic_sci_trigger = 0; /* force level trigger */ + if (strncmp(str, "edge", 4) == 0) + acpi_pic_sci_trigger = 1; /* force edge trigger */ + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("acpi_pic_sci=", acpi_pic_sci_setup); + #endif /* CONFIG_ACPI_BUS */ static unsigned long __init @@ -354,8 +393,10 @@ * Initialize the ACPI boot-time table parser. */ result = acpi_table_init(); - if (result) + if (result) { + acpi_disabled = 1; return result; + } result = acpi_blacklisted(); if (result) { @@ -442,7 +483,7 @@ * If MPS is present, it will handle them, * otherwise the system will stay in PIC mode */ - if (acpi_disabled) { + if (acpi_disabled || acpi_noirq) { return 1; } @@ -484,6 +525,8 @@ acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_balance_set(NULL); + acpi_ioapic = 1; #endif /*CONFIG_X86_IO_APIC*/ diff -urN linux-2.6.2-rc2/arch/x86_64/kernel/io_apic.c linux-2.6.2-rc3/arch/x86_64/kernel/io_apic.c --- linux-2.6.2-rc2/arch/x86_64/kernel/io_apic.c 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/arch/x86_64/kernel/io_apic.c 2004-01-30 18:49:19.000000000 -0800 @@ -1121,8 +1121,6 @@ unsigned char old_id; unsigned long flags; - if (acpi_ioapic) return; /* ACPI does that already */ - /* * Set the IOAPIC ID to the value stored in the MPC table. */ @@ -1751,12 +1749,14 @@ /* * Set up the IO-APIC IRQ routing table. */ - setup_ioapic_ids_from_mpc(); + if (!acpi_ioapic) + setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - print_IO_APIC(); + if (!acpi_ioapic) + print_IO_APIC(); } /* Ensure the ACPI SCI interrupt level is active low, edge-triggered */ diff -urN linux-2.6.2-rc2/arch/x86_64/kernel/mpparse.c linux-2.6.2-rc3/arch/x86_64/kernel/mpparse.c --- linux-2.6.2-rc2/arch/x86_64/kernel/mpparse.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/arch/x86_64/kernel/mpparse.c 2004-01-30 18:49:19.000000000 -0800 @@ -951,6 +951,8 @@ entry->irq); } + print_IO_APIC(); + return; } diff -urN linux-2.6.2-rc2/arch/x86_64/kernel/setup.c linux-2.6.2-rc3/arch/x86_64/kernel/setup.c --- linux-2.6.2-rc2/arch/x86_64/kernel/setup.c 2004-01-08 22:59:06.000000000 -0800 +++ linux-2.6.2-rc3/arch/x86_64/kernel/setup.c 2004-01-30 18:49:19.000000000 -0800 @@ -65,7 +65,11 @@ EXPORT_SYMBOL_GPL(mmu_cr4_features); int acpi_disabled = 0; -int acpi_ht = 0; + +#ifdef CONFIG_ACPI_BOOT +extern int __initdata acpi_ht; +/* int __initdata acpi_force = 0; */ +#endif /* For PCI or other memory-mapped resources */ unsigned long pci_mem_start = 0x10000000; @@ -195,6 +199,7 @@ if (c != ' ') goto next_char; +#ifdef CONFIG_ACPI_BOOT /* "acpi=off" disables both ACPI table parsing and interpreter init */ if (!memcmp(from, "acpi=off", 8)) acpi_disabled = 1; @@ -210,6 +215,7 @@ if (!memcmp(from, "acpi=ht", 7)) { acpi_ht = 1; } +#endif if (!memcmp(from, "nolapic", 7) || !memcmp(from, "disableapic", 11)) diff -urN linux-2.6.2-rc2/arch/x86_64/mm/extable.c linux-2.6.2-rc3/arch/x86_64/mm/extable.c --- linux-2.6.2-rc2/arch/x86_64/mm/extable.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/x86_64/mm/extable.c 2004-01-30 18:49:19.000000000 -0800 @@ -55,5 +55,4 @@ } } } while (change != 0); - return 0; } diff -urN linux-2.6.2-rc2/arch/x86_64/mm/k8topology.c linux-2.6.2-rc3/arch/x86_64/mm/k8topology.c --- linux-2.6.2-rc2/arch/x86_64/mm/k8topology.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/arch/x86_64/mm/k8topology.c 2004-01-30 18:49:19.000000000 -0800 @@ -75,7 +75,7 @@ continue; } if (nodeid >= numnodes) { - printk("Ignoring excess node %d (%x:%x)\n", nodeid, + printk("Ignoring excess node %d (%lx:%lx)\n", nodeid, base, limit); continue; } diff -urN linux-2.6.2-rc2/crypto/sha256.c linux-2.6.2-rc3/crypto/sha256.c --- linux-2.6.2-rc2/crypto/sha256.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/crypto/sha256.c 2004-01-30 18:49:19.000000000 -0800 @@ -295,7 +295,7 @@ u8 bits[8]; unsigned int index, pad_len, t; int i, j; - const u8 padding[64] = { 0x80, }; + static const u8 padding[64] = { 0x80, }; /* Save number of bits */ t = sctx->count[0]; diff -urN linux-2.6.2-rc2/drivers/acpi/ac.c linux-2.6.2-rc3/drivers/acpi/ac.c --- linux-2.6.2-rc2/drivers/acpi/ac.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/ac.c 2004-01-30 18:49:19.000000000 -0800 @@ -108,7 +108,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_ac_dir = NULL; +struct proc_dir_entry *acpi_ac_dir; int acpi_ac_seq_show(struct seq_file *seq, void *offset) { diff -urN linux-2.6.2-rc2/drivers/acpi/asus_acpi.c linux-2.6.2-rc3/drivers/acpi/asus_acpi.c --- linux-2.6.2-rc2/drivers/acpi/asus_acpi.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/asus_acpi.c 2004-01-30 18:49:19.000000000 -0800 @@ -73,8 +73,8 @@ MODULE_LICENSE("GPL"); -static uid_t asus_uid = 0; -static gid_t asus_gid = 0; +static uid_t asus_uid; +static gid_t asus_gid; MODULE_PARM(asus_uid, "i"); MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n"); MODULE_PARM(asus_gid, "i"); @@ -192,14 +192,14 @@ }; /* procdir we use */ -static struct proc_dir_entry *asus_proc_dir = NULL; +static struct proc_dir_entry *asus_proc_dir; /* * This header is made available to allow proper configuration given model, * revision number , ... this info cannot go in struct asus_hotk because it is * available before the hotk */ -static struct acpi_table_header *asus_info = NULL; +static struct acpi_table_header *asus_info; /* * The hotkey driver declaration diff -urN linux-2.6.2-rc2/drivers/acpi/battery.c linux-2.6.2-rc3/drivers/acpi/battery.c --- linux-2.6.2-rc2/drivers/acpi/battery.c 2004-01-08 22:59:55.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/battery.c 2004-01-30 18:49:19.000000000 -0800 @@ -340,7 +340,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_battery_dir = NULL; +struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_read_info ( diff -urN linux-2.6.2-rc2/drivers/acpi/bus.c linux-2.6.2-rc3/drivers/acpi/bus.c --- linux-2.6.2-rc2/drivers/acpi/bus.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/bus.c 2004-01-30 18:49:19.000000000 -0800 @@ -39,7 +39,7 @@ #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME ("acpi_bus") -extern void acpi_pic_set_level_irq(unsigned int irq); +extern void __init acpi_pic_sci_set_trigger(unsigned int irq); FADT_DESCRIPTOR acpi_fadt; struct acpi_device *acpi_root; @@ -615,7 +615,7 @@ if (acpi_ioapic) mp_config_ioapic_for_sci(acpi_fadt.sci_int); else - acpi_pic_set_level_irq(acpi_fadt.sci_int); + acpi_pic_sci_set_trigger(acpi_fadt.sci_int); #endif status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); diff -urN linux-2.6.2-rc2/drivers/acpi/button.c linux-2.6.2-rc3/drivers/acpi/button.c --- linux-2.6.2-rc2/drivers/acpi/button.c 2004-01-08 22:59:06.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/button.c 2004-01-30 18:49:19.000000000 -0800 @@ -107,7 +107,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -static struct proc_dir_entry *acpi_button_dir = NULL; +static struct proc_dir_entry *acpi_button_dir; static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) { diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsfield.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsfield.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsfield.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsfield.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsinit.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsinit.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsinit.c 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsinit.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -106,7 +106,7 @@ status = acpi_ds_initialize_region (obj_handle); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n", - obj_handle, ((struct acpi_namespace_node *) obj_handle)->name.ascii, + obj_handle, acpi_ut_get_node_name (obj_handle), acpi_format_exception (status))); } @@ -141,7 +141,7 @@ status = acpi_ds_parse_method (obj_handle); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", - obj_handle, ((struct acpi_namespace_node *) obj_handle)->name.ascii, + obj_handle, acpi_ut_get_node_name (obj_handle), acpi_format_exception (status))); /* This parse failed, but we will continue parsing more methods */ diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsmethod.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsmethod.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsmethod.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsmethod.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,7 +94,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", - ((struct acpi_namespace_node *) obj_handle)->name.ascii, obj_handle)); + acpi_ut_get_node_name (obj_handle), obj_handle)); /* Extract the method object from the method Node */ @@ -169,7 +169,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", - ((struct acpi_namespace_node *) obj_handle)->name.ascii, obj_handle, op)); + acpi_ut_get_node_name (obj_handle), obj_handle, op)); acpi_ps_delete_parse_tree (op); return_ACPI_STATUS (status); diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsmthdat.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsmthdat.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsmthdat.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsmthdat.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -567,13 +567,13 @@ acpi_status status; struct acpi_namespace_node *node; union acpi_operand_object *current_obj_desc; + union acpi_operand_object *new_obj_desc; ACPI_FUNCTION_TRACE ("ds_store_object_to_local"); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%d Idx=%d Obj=%p\n", opcode, index, obj_desc)); - /* Parameter validation */ if (!obj_desc) { @@ -595,6 +595,18 @@ } /* + * If the reference count on the object is more than one, we must + * take a copy of the object before we store. + */ + new_obj_desc = obj_desc; + if (obj_desc->common.reference_count > 1) { + status = acpi_ut_copy_iobject_to_iobject (obj_desc, &new_obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + /* * If there is an object already in this slot, we either * have to delete it, or if this is an argument and there * is an object reference stored there, we have to do @@ -624,8 +636,8 @@ * operand objects of type Reference. */ if (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) != ACPI_DESC_TYPE_OPERAND) { - ACPI_REPORT_ERROR (("Invalid descriptor type while storing to method arg: %X\n", - current_obj_desc->common.type)); + ACPI_REPORT_ERROR (("Invalid descriptor type while storing to method arg: [%s]\n", + acpi_ut_get_descriptor_name (current_obj_desc))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -636,15 +648,21 @@ if ((current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && (current_obj_desc->reference.opcode == AML_REF_OF_OP)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "Arg (%p) is an obj_ref(Node), storing in node %p\n", - obj_desc, current_obj_desc)); + "Arg (%p) is an obj_ref(Node), storing in node %p\n", + new_obj_desc, current_obj_desc)); /* * Store this object to the Node * (perform the indirect store) */ - status = acpi_ex_store_object_to_node (obj_desc, + status = acpi_ex_store_object_to_node (new_obj_desc, current_obj_desc->reference.object, walk_state); + + /* Remove local reference if we copied the object above */ + + if (new_obj_desc != obj_desc) { + acpi_ut_remove_reference (new_obj_desc); + } return_ACPI_STATUS (status); } } @@ -657,12 +675,18 @@ } /* - * Install the obj_stack descriptor (*obj_desc) into + * Install the Obj descriptor (*new_obj_desc) into * the descriptor for the Arg or Local. - * Install the new object in the stack entry * (increments the object reference count by one) */ - status = acpi_ds_method_data_set_value (opcode, index, obj_desc, walk_state); + status = acpi_ds_method_data_set_value (opcode, index, new_obj_desc, walk_state); + + /* Remove local reference if we copied the object above */ + + if (new_obj_desc != obj_desc) { + acpi_ut_remove_reference (new_obj_desc); + } + return_ACPI_STATUS (status); } diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsobject.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsobject.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsobject.c 2004-01-08 22:59:05.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsobject.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsopcode.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsopcode.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsopcode.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsopcode.c 2004-01-30 18:49:19.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -201,7 +201,7 @@ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL)); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n", - node->name.ascii)); + acpi_ut_get_node_name (node))); /* Execute the AML code for the term_arg arguments */ @@ -346,7 +346,7 @@ ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL)); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] op_region Arg Init at AML %p\n", - node->name.ascii, extra_desc->extra.aml_start)); + acpi_ut_get_node_name (node), extra_desc->extra.aml_start)); /* Execute the argument AML */ @@ -438,8 +438,8 @@ * after resolution in acpi_ex_resolve_operands(). */ if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination must be a NS Node\n", - acpi_ps_get_opcode_name (aml_opcode))); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination not a NS Node [%s]\n", + acpi_ps_get_opcode_name (aml_opcode), acpi_ut_get_descriptor_name (result_desc))); status = AE_AML_OPERAND_TYPE; goto cleanup; @@ -514,14 +514,16 @@ goto cleanup; } - /* Entire field must fit within the current length of the buffer */ if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Field size %d exceeds Buffer size %d (bits)\n", - bit_offset + bit_count, 8 * (u32) buffer_desc->buffer.length)); + "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n", + acpi_ut_get_node_name (result_desc), + bit_offset + bit_count, + acpi_ut_get_node_name (buffer_desc->buffer.node), + 8 * (u32) buffer_desc->buffer.length)); status = AE_AML_BUFFER_LIMIT; goto cleanup; } @@ -742,7 +744,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n", obj_desc, - ACPI_HIDWORD (obj_desc->region.address), ACPI_LODWORD (obj_desc->region.address), + ACPI_FORMAT_UINT64 (obj_desc->region.address), obj_desc->region.length)); /* Now the address and length are valid for this opregion */ diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dsutils.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dsutils.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dsutils.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dsutils.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dswexec.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dswexec.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dswexec.c 2004-01-08 23:00:05.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dswexec.c 2004-01-30 18:49:19.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -416,10 +416,24 @@ status = acpi_gbl_op_type_dispatch [op_type] (walk_state); } else { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "[%s]: Could not resolve operands, %s\n", - acpi_ps_get_opcode_name (walk_state->opcode), - acpi_format_exception (status))); + /* + * Treat constructs of the form "Store(local_x,local_x)" as noops when the + * Local is uninitialized. + */ + if ((status == AE_AML_UNINITIALIZED_LOCAL) && + (walk_state->opcode == AML_STORE_OP) && + (walk_state->operands[0]->common.type == ACPI_TYPE_LOCAL_REFERENCE) && + (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) && + (walk_state->operands[0]->reference.opcode == + walk_state->operands[1]->reference.opcode)) { + status = AE_OK; + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "[%s]: Could not resolve operands, %s\n", + acpi_ps_get_opcode_name (walk_state->opcode), + acpi_format_exception (status))); + } } /* Always delete the argument objects and clear the operand stack */ diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dswload.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dswload.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dswload.c 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dswload.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -167,7 +167,7 @@ object_type = walk_state->op_info->object_type; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "State=%p Op=%p [%s] ", walk_state, op, acpi_ut_get_type_name (object_type))); + "State=%p Op=%p [%s]\n", walk_state, op, acpi_ut_get_type_name (object_type))); switch (walk_state->opcode) { case AML_SCOPE_OP: @@ -260,10 +260,12 @@ if ((walk_state->opcode != AML_SCOPE_OP) && (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { flags |= ACPI_NS_ERROR_IF_FOUND; - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Cannot already exist\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", + acpi_ut_get_type_name (object_type))); } else { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Both Find or Create allowed\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n", + acpi_ut_get_type_name (object_type))); } /* diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dswscope.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dswscope.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dswscope.c 2004-01-08 23:00:12.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dswscope.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -146,7 +146,7 @@ if (old_scope_info) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[%4.4s] (%s)", - old_scope_info->scope.node->name.ascii, + acpi_ut_get_node_name (old_scope_info->scope.node), acpi_ut_get_type_name (old_scope_info->common.value))); } else { @@ -156,7 +156,7 @@ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, ", New scope -> [%4.4s] (%s)\n", - scope_info->scope.node->name.ascii, + acpi_ut_get_node_name (scope_info->scope.node), acpi_ut_get_type_name (scope_info->common.value))); /* Push new scope object onto stack */ @@ -207,14 +207,14 @@ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", (u32) walk_state->scope_depth, - scope_info->scope.node->name.ascii, + acpi_ut_get_node_name (scope_info->scope.node), acpi_ut_get_type_name (scope_info->common.value))); new_scope_info = walk_state->scope_info; if (new_scope_info) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[%4.4s] (%s)\n", - new_scope_info->scope.node->name.ascii, + acpi_ut_get_node_name (new_scope_info->scope.node), acpi_ut_get_type_name (new_scope_info->common.value))); } else { diff -urN linux-2.6.2-rc2/drivers/acpi/dispatcher/dswstate.c linux-2.6.2-rc3/drivers/acpi/dispatcher/dswstate.c --- linux-2.6.2-rc2/drivers/acpi/dispatcher/dswstate.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/dispatcher/dswstate.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/ec.c linux-2.6.2-rc3/drivers/acpi/ec.c --- linux-2.6.2-rc2/drivers/acpi/ec.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/ec.c 2004-01-30 18:49:19.000000000 -0800 @@ -475,7 +475,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_ec_dir = NULL; +struct proc_dir_entry *acpi_ec_dir; static int diff -urN linux-2.6.2-rc2/drivers/acpi/events/evevent.c linux-2.6.2-rc3/drivers/acpi/events/evevent.c --- linux-2.6.2-rc2/drivers/acpi/events/evevent.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evevent.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/events/evgpe.c linux-2.6.2-rc3/drivers/acpi/events/evgpe.c --- linux-2.6.2-rc2/drivers/acpi/events/evgpe.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evgpe.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -139,12 +139,10 @@ { u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u8 enabled_status_byte; - u8 bit_mask; struct acpi_gpe_register_info *gpe_register_info; u32 in_value; acpi_status status; struct acpi_gpe_block_info *gpe_block; - u32 gpe_number; u32 i; u32 j; @@ -187,11 +185,9 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n", - ACPI_HIDWORD (gpe_register_info->status_address.address), - ACPI_LODWORD (gpe_register_info->status_address.address), + ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address), gpe_register_info->status, - ACPI_HIDWORD (gpe_register_info->enable_address.address), - ACPI_LODWORD (gpe_register_info->enable_address.address), + ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address), gpe_register_info->enable)); /* First check if there is anything active at all in this register */ @@ -206,19 +202,17 @@ /* Now look at the individual GPEs in this byte register */ - for (j = 0, bit_mask = 1; j < ACPI_GPE_REGISTER_WIDTH; j++, bit_mask <<= 1) { + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Examine one GPE bit */ - if (enabled_status_byte & bit_mask) { + if (enabled_status_byte & acpi_gbl_decode_to8bit[j]) { /* * Found an active GPE. Dispatch the event to a handler * or method. */ - gpe_number = (i * ACPI_GPE_REGISTER_WIDTH) + j; - int_status |= acpi_ev_gpe_dispatch ( - &gpe_block->event_info[gpe_number], - j + gpe_register_info->base_gpe_number); + &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j], + j + gpe_register_info->base_gpe_number); } } } @@ -294,7 +288,7 @@ if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception (status), - local_gpe_event_info.method_node->name.ascii, gpe_number)); + acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number)); } } @@ -367,6 +361,18 @@ /* Invoke the installed handler (at interrupt level) */ gpe_event_info->handler (gpe_event_info->context); + + /* It is now safe to clear level-triggered events. */ + + if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) { + status = acpi_hw_clear_gpe (gpe_event_info); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (( + "acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n", + gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + } + } } else if (gpe_event_info->method_node) { /* @@ -375,13 +381,16 @@ */ status = acpi_hw_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", + ACPI_REPORT_ERROR (( + "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } - /* Execute the method associated with the GPE. */ - + /* + * Execute the method associated with the GPE + * NOTE: Level-triggered GPEs are cleared after the method completes. + */ if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE, acpi_ev_asynch_execute_gpe_method, gpe_event_info))) { @@ -399,22 +408,12 @@ /* * Disable the GPE. The GPE will remain disabled until the ACPI - * Core Subsystem is restarted, or the handler is reinstalled. + * Core Subsystem is restarted, or a handler is installed. */ status = acpi_hw_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", - gpe_number)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); - } - } - - /* It is now safe to clear level-triggered events. */ - - if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) { - status = acpi_hw_clear_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n", + ACPI_REPORT_ERROR (( + "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } diff -urN linux-2.6.2-rc2/drivers/acpi/events/evgpeblk.c linux-2.6.2-rc3/drivers/acpi/events/evgpeblk.c --- linux-2.6.2-rc2/drivers/acpi/events/evgpeblk.c 2004-01-08 22:59:42.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evgpeblk.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -477,7 +477,7 @@ * * RETURN: Status * - * DESCRIPTION: Install new GPE block with mutex support + * DESCRIPTION: Remove a GPE block * ******************************************************************************/ @@ -743,8 +743,7 @@ ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), gpe_device->name.ascii, gpe_block->register_count, - ACPI_HIDWORD (gpe_block->block_address.address), - ACPI_LODWORD (gpe_block->block_address.address), + ACPI_FORMAT_UINT64 (gpe_block->block_address.address), interrupt_level)); /* Find all GPE methods (_Lxx, _Exx) for this block */ diff -urN linux-2.6.2-rc2/drivers/acpi/events/evmisc.c linux-2.6.2-rc3/drivers/acpi/events/evmisc.c --- linux-2.6.2-rc2/drivers/acpi/events/evmisc.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evmisc.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -195,7 +195,8 @@ /* There is no per-device notify handler for this device */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "No notify handler for [%4.4s] node %p\n", node->name.ascii, node)); + "No notify handler for [%4.4s] node %p\n", + acpi_ut_get_node_name (node), node)); } return (status); diff -urN linux-2.6.2-rc2/drivers/acpi/events/evregion.c linux-2.6.2-rc3/drivers/acpi/events/evregion.c --- linux-2.6.2-rc2/drivers/acpi/events/evregion.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evregion.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ #define ACPI_NUM_DEFAULT_SPACES 4 -u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { +static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_ADR_SPACE_SYSTEM_IO, ACPI_ADR_SPACE_PCI_CONFIG, @@ -136,7 +136,7 @@ * ******************************************************************************/ -static acpi_status +acpi_status acpi_ev_execute_reg_method ( union acpi_operand_object *region_obj, u32 function) @@ -202,7 +202,7 @@ * * FUNCTION: acpi_ev_address_space_dispatch * - * PARAMETERS: region_obj - internal region object + * PARAMETERS: region_obj - Internal region object * space_id - ID of the address space (0-255) * Function - Read or Write operation * Address - Where in the space to read or write @@ -243,9 +243,11 @@ /* Ensure that there is a handler associated with this region */ - handler_desc = region_obj->region.address_space; + handler_desc = region_obj->region.handler; if (!handler_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "No handler for Region [%4.4s] (%p) [%s]\n", + acpi_ut_get_node_name (region_obj->region.node), region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); return_ACPI_STATUS (AE_NOT_EXIST); @@ -320,8 +322,8 @@ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", - ®ion_obj->region.address_space->address_space, handler, - ACPI_HIDWORD (address), ACPI_LODWORD (address), + ®ion_obj->region.handler->address_space, handler, + ACPI_FORMAT_UINT64 (address), acpi_ut_get_region_name (region_obj->region.space_id))); if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { @@ -359,6 +361,7 @@ return_ACPI_STATUS (status); } + /******************************************************************************* * * FUNCTION: acpi_ev_detach_region @@ -398,7 +401,7 @@ /* Get the address handler from the region object */ - handler_obj = region_obj->region.address_space; + handler_obj = region_obj->region.handler; if (!handler_obj) { /* This region has no handler, all done */ @@ -472,7 +475,7 @@ * If the region is on the handler's list * this better be the region's handler */ - region_obj->region.address_space = NULL; + region_obj->region.handler = NULL; acpi_ut_remove_reference (handler_obj); return_VOID; @@ -515,17 +518,15 @@ union acpi_operand_object *region_obj, u8 acpi_ns_is_locked) { - acpi_status status; - acpi_status status2; - ACPI_FUNCTION_TRACE ("ev_attach_region"); ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, - "Adding Region %p to address handler %p [%s]\n", - region_obj, handler_obj, acpi_ut_get_region_name (region_obj->region.space_id))); - + "Adding Region [%4.4s] %p to address handler %p [%s]\n", + acpi_ut_get_node_name (region_obj->region.node), + region_obj, handler_obj, + acpi_ut_get_region_name (region_obj->region.space_id))); /* Link this region to the front of the handler's list */ @@ -534,34 +535,14 @@ /* Install the region's handler */ - if (region_obj->region.address_space) { + if (region_obj->region.handler) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } - region_obj->region.address_space = handler_obj; + region_obj->region.handler = handler_obj; acpi_ut_add_reference (handler_obj); - /* - * Tell all users that this region is usable by running the _REG - * method - */ - if (acpi_ns_is_locked) { - status2 = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status2)) { - return_ACPI_STATUS (status2); - } - } - - status = acpi_ev_execute_reg_method (region_obj, 1); - - if (acpi_ns_is_locked) { - status2 = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status2)) { - return_ACPI_STATUS (status2); - } - } - - return_ACPI_STATUS (status); + return_ACPI_STATUS (AE_OK); } @@ -569,9 +550,7 @@ * * FUNCTION: acpi_ev_install_handler * - * PARAMETERS: Handle - Node to be dumped - * Level - Nesting level of the handle - * Context - Passed into acpi_ns_walk_namespace + * PARAMETERS: walk_namespace callback * * DESCRIPTION: This routine installs an address handler into objects that are * of type Region or Device. @@ -640,7 +619,7 @@ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ - next_handler_obj = obj_desc->device.address_space; + next_handler_obj = obj_desc->device.handler; while (next_handler_obj) { /* Found a handler, is it for the same address space? */ @@ -697,4 +676,74 @@ return (status); } +/******************************************************************************* + * + * FUNCTION: acpi_ev_reg_run + * + * PARAMETERS: walk_namespace callback + * + * DESCRIPTION: Run _REg method for region objects of the requested space_iD + * + ******************************************************************************/ + +acpi_status +acpi_ev_reg_run ( + acpi_handle obj_handle, + u32 level, + void *context, + void **return_value) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + + + handler_obj = (union acpi_operand_object *) context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node (obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions.and objects + * that are allowed to have address space handlers + */ + if ((node->type != ACPI_TYPE_REGION) && + (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { + /* No object, just exit */ + + return (AE_OK); + } + + + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { + /* + * This region is for a different address space + * -- just ignore it + */ + return (AE_OK); + } + + status = acpi_ev_execute_reg_method (obj_desc, 1); + return (status); +} diff -urN linux-2.6.2-rc2/drivers/acpi/events/evrgnini.c linux-2.6.2-rc3/drivers/acpi/events/evrgnini.c --- linux-2.6.2-rc2/drivers/acpi/events/evrgnini.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evrgnini.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -177,7 +177,7 @@ ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup"); - handler_obj = region_obj->region.address_space; + handler_obj = region_obj->region.handler; if (!handler_obj) { /* * No installed handler. This shouldn't happen because the dispatch @@ -239,7 +239,7 @@ else { ACPI_REPORT_ERROR (( "Could not install pci_config handler for Root Bridge %4.4s, %s\n", - pci_root_node->name.ascii, acpi_format_exception (status))); + acpi_ut_get_node_name (pci_root_node), acpi_format_exception (status))); } } break; @@ -469,7 +469,7 @@ /* Setup defaults */ - region_obj->region.address_space = NULL; + region_obj->region.handler = NULL; region_obj2->extra.method_REG = NULL; region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; @@ -502,17 +502,17 @@ switch (node->type) { case ACPI_TYPE_DEVICE: - handler_obj = obj_desc->device.address_space; + handler_obj = obj_desc->device.handler; break; case ACPI_TYPE_PROCESSOR: - handler_obj = obj_desc->processor.address_space; + handler_obj = obj_desc->processor.handler; break; case ACPI_TYPE_THERMAL: - handler_obj = obj_desc->thermal_zone.address_space; + handler_obj = obj_desc->thermal_zone.handler; break; default: @@ -533,6 +533,26 @@ status = acpi_ev_attach_region (handler_obj, region_obj, acpi_ns_locked); + /* + * Tell all users that this region is usable by running the _REG + * method + */ + if (acpi_ns_locked) { + status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + status = acpi_ev_execute_reg_method (region_obj, 1); + + if (acpi_ns_locked) { + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + return_ACPI_STATUS (AE_OK); } diff -urN linux-2.6.2-rc2/drivers/acpi/events/evsci.c linux-2.6.2-rc3/drivers/acpi/events/evsci.c --- linux-2.6.2-rc2/drivers/acpi/events/evsci.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evsci.c 2004-01-30 18:49:19.000000000 -0800 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/events/evxface.c linux-2.6.2-rc3/drivers/acpi/events/evxface.c --- linux-2.6.2-rc2/drivers/acpi/events/evxface.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evxface.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/events/evxfevnt.c linux-2.6.2-rc3/drivers/acpi/events/evxfevnt.c --- linux-2.6.2-rc2/drivers/acpi/events/evxfevnt.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evxfevnt.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/events/evxfregn.c linux-2.6.2-rc3/drivers/acpi/events/evxfregn.c --- linux-2.6.2-rc2/drivers/acpi/events/evxfregn.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/events/evxfregn.c 2004-01-30 18:49:19.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -173,7 +173,7 @@ * The attached device object already exists. * Make sure the handler is not already installed. */ - handler_obj = obj_desc->device.address_space; + handler_obj = obj_desc->device.handler; /* Walk the handler list for this device */ @@ -240,7 +240,8 @@ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", - acpi_ut_get_region_name (space_id), space_id, node->name.ascii, node, obj_desc)); + acpi_ut_get_region_name (space_id), space_id, + acpi_ut_get_node_name (node), node, obj_desc)); /* * Install the handler @@ -267,13 +268,13 @@ /* Install at head of Device.address_space list */ - handler_obj->address_space.next = obj_desc->device.address_space; + handler_obj->address_space.next = obj_desc->device.handler; /* * The Device object is the first reference on the handler_obj. * Each region that uses the handler adds a reference. */ - obj_desc->device.address_space = handler_obj; + obj_desc->device.handler = handler_obj; /* * Walk the namespace finding all of the regions this @@ -291,6 +292,17 @@ ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler, handler_obj, NULL); + /* + * Now we can run the _REG methods for all Regions for this + * space ID. This is a separate walk in order to handle any + * interdependencies between regions and _REG methods. (i.e. handlers + * must be installed for all regions of this Space ID before we + * can run any _REG methods. + */ + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, + handler_obj, NULL); + unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); @@ -357,8 +369,8 @@ /* Find the address handler the user requested */ - handler_obj = obj_desc->device.address_space; - last_obj_ptr = &obj_desc->device.address_space; + handler_obj = obj_desc->device.handler; + last_obj_ptr = &obj_desc->device.handler; while (handler_obj) { /* We have a handler, see if user requested this one */ diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exconfig.c linux-2.6.2-rc3/drivers/acpi/executer/exconfig.c --- linux-2.6.2-rc2/drivers/acpi/executer/exconfig.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exconfig.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exconvrt.c linux-2.6.2-rc3/drivers/acpi/executer/exconvrt.c --- linux-2.6.2-rc2/drivers/acpi/executer/exconvrt.c 2004-01-08 22:59:06.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exconvrt.c 2004-01-30 18:49:19.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/excreate.c linux-2.6.2-rc3/drivers/acpi/executer/excreate.c --- linux-2.6.2-rc2/drivers/acpi/executer/excreate.c 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/excreate.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exdump.c linux-2.6.2-rc3/drivers/acpi/executer/exdump.c --- linux-2.6.2-rc2/drivers/acpi/executer/exdump.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exdump.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,27 +89,27 @@ if (!obj_desc) { /* - * This usually indicates that something serious is wrong -- - * since most (if not all) - * code that dumps the stack expects something to be there! + * This usually indicates that something serious is wrong */ - acpi_os_printf ("Null stack entry ptr\n"); + acpi_os_printf ("Null Object Descriptor\n"); return; } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p NS Node: ", obj_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc)); ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC); return; } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is not a local object\n", obj_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%p is not a node or operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name (obj_desc))); ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object)); return; } - /* obj_desc is a valid object */ + /* obj_desc is a valid object */ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc)); @@ -151,11 +151,10 @@ obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { - /* Value is a Number */ + /* Value is an Integer */ acpi_os_printf (" value is [%8.8X%8.8x]", - ACPI_HIDWORD(obj_desc->integer.value), - ACPI_LODWORD(obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); } acpi_os_printf ("\n"); @@ -169,11 +168,10 @@ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { - /* Value is a Number */ + /* Value is an Integer */ acpi_os_printf (" value is [%8.8X%8.8x]", - ACPI_HIDWORD(obj_desc->integer.value), - ACPI_LODWORD(obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); } acpi_os_printf ("\n"); @@ -189,7 +187,7 @@ default: - /* unknown opcode */ + /* Unknown opcode */ acpi_os_printf ("Unknown Reference opcode=%X\n", obj_desc->reference.opcode); @@ -229,8 +227,7 @@ case ACPI_TYPE_INTEGER: acpi_os_printf ("Integer %8.8X%8.8X\n", - ACPI_HIDWORD (obj_desc->integer.value), - ACPI_LODWORD (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; @@ -271,8 +268,7 @@ } else { acpi_os_printf (" base %8.8X%8.8X Length %X\n", - ACPI_HIDWORD (obj_desc->region.address), - ACPI_LODWORD (obj_desc->region.address), + ACPI_FORMAT_UINT64 (obj_desc->region.address), obj_desc->region.length); } break; @@ -494,7 +490,7 @@ acpi_os_printf ("%20s : %p\n", title, value); #else acpi_os_printf ("%20s : %8.8X%8.8X\n", title, - ACPI_HIDWORD (value), ACPI_LODWORD (value)); + ACPI_FORMAT_UINT64 (value)); #endif } @@ -525,7 +521,7 @@ } } - acpi_os_printf ("%20s : %4.4s\n", "Name", node->name.ascii); + acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node)); acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type)); acpi_ex_out_integer ("Flags", node->flags); acpi_ex_out_integer ("Owner Id", node->owner_id); @@ -573,7 +569,8 @@ } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf ("ex_dump_object_descriptor: %p is not a valid ACPI object\n", obj_desc); + acpi_os_printf ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name (obj_desc)); return_VOID; } @@ -589,8 +586,7 @@ case ACPI_TYPE_INTEGER: acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value", - ACPI_HIDWORD (obj_desc->integer.value), - ACPI_LODWORD (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; @@ -635,7 +631,7 @@ case ACPI_TYPE_DEVICE: - acpi_ex_out_pointer ("address_space", obj_desc->device.address_space); + acpi_ex_out_pointer ("Handler", obj_desc->device.handler); acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify); break; @@ -673,7 +669,7 @@ acpi_ex_out_integer ("Flags", obj_desc->region.flags); acpi_ex_out_address ("Address", obj_desc->region.address); acpi_ex_out_integer ("Length", obj_desc->region.length); - acpi_ex_out_pointer ("address_space", obj_desc->region.address_space); + acpi_ex_out_pointer ("Handler", obj_desc->region.handler); acpi_ex_out_pointer ("Next", obj_desc->region.next); break; @@ -694,7 +690,7 @@ acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify); - acpi_ex_out_pointer ("address_space", obj_desc->processor.address_space); + acpi_ex_out_pointer ("Handler", obj_desc->processor.handler); break; @@ -702,7 +698,7 @@ acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify); - acpi_ex_out_pointer ("address_space", obj_desc->thermal_zone.address_space); + acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler); break; diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exfield.c linux-2.6.2-rc3/drivers/acpi/executer/exfield.c --- linux-2.6.2-rc2/drivers/acpi/executer/exfield.c 2004-01-08 22:59:06.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exfield.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exfldio.c linux-2.6.2-rc3/drivers/acpi/executer/exfldio.c --- linux-2.6.2-rc2/drivers/acpi/executer/exfldio.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exfldio.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -138,8 +138,9 @@ */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", - obj_desc->common_field.node->name.ascii, obj_desc->common_field.access_byte_width, - rgn_desc->region.node->name.ascii, rgn_desc->region.length)); + acpi_ut_get_node_name (obj_desc->common_field.node), + obj_desc->common_field.access_byte_width, + acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); } /* @@ -148,9 +149,10 @@ */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", - obj_desc->common_field.node->name.ascii, obj_desc->common_field.base_byte_offset, + acpi_ut_get_node_name (obj_desc->common_field.node), + obj_desc->common_field.base_byte_offset, field_datum_byte_offset, obj_desc->common_field.access_byte_width, - rgn_desc->region.node->name.ascii, rgn_desc->region.length)); + acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); #ifdef CONFIG_ACPI_RELAXED_AML { @@ -261,7 +263,7 @@ obj_desc->common_field.access_byte_width, obj_desc->common_field.base_byte_offset, field_datum_byte_offset, - ACPI_HIDWORD (address), ACPI_LODWORD (address))); + ACPI_FORMAT_UINT64 (address))); /* Invoke the appropriate address_space/op_region handler */ @@ -514,12 +516,12 @@ if (ACPI_SUCCESS (status)) { if (read_write == ACPI_READ) { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n", - ACPI_HIDWORD (*value), ACPI_LODWORD (*value), + ACPI_FORMAT_UINT64 (*value), obj_desc->common_field.access_byte_width)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", - ACPI_HIDWORD (*value), ACPI_LODWORD (*value), + ACPI_FORMAT_UINT64 (*value), obj_desc->common_field.access_byte_width)); } } @@ -612,11 +614,11 @@ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", - ACPI_HIDWORD (mask), ACPI_LODWORD (mask), + ACPI_FORMAT_UINT64 (mask), field_datum_byte_offset, obj_desc->common_field.access_byte_width, - ACPI_HIDWORD (field_value), ACPI_LODWORD (field_value), - ACPI_HIDWORD (merged_value),ACPI_LODWORD (merged_value))); + ACPI_FORMAT_UINT64 (field_value), + ACPI_FORMAT_UINT64 (merged_value))); /* Write the merged value */ @@ -784,12 +786,13 @@ { acpi_status status; u32 field_datum_byte_offset; - u32 datum_offset; - acpi_integer previous_raw_datum; + u32 buffer_datum_offset; + acpi_integer previous_raw_datum = 0; acpi_integer this_raw_datum = 0; acpi_integer merged_datum = 0; u32 byte_field_length; u32 datum_count; + u32 i; ACPI_FUNCTION_TRACE ("ex_extract_from_field"); @@ -812,77 +815,74 @@ datum_count = ACPI_ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); + /* + * If the field is not aligned on a datum boundary and does not + * fit within a single datum, we must read an extra datum. + * + * We could just split the aligned and non-aligned cases since the + * aligned case is so very simple, but this would require more code. + */ + if ((obj_desc->common_field.end_field_valid_bits != 0) && + (!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) { + datum_count++; + } + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "byte_len %X, datum_len %X, byte_gran %X\n", byte_field_length, datum_count,obj_desc->common_field.access_byte_width)); /* * Clear the caller's buffer (the whole buffer length as given) - * This is very important, especially in the cases where a byte is read, - * but the buffer is really a u32 (4 bytes). + * This is very important, especially in the cases where the buffer + * is longer than the size of the field. */ ACPI_MEMSET (buffer, 0, buffer_length); - /* Read the first raw datum to prime the loop */ - field_datum_byte_offset = 0; - datum_offset= 0; - - status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, - &previous_raw_datum, ACPI_READ); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - + buffer_datum_offset= 0; - /* We might actually be done if the request fits in one datum */ + /* Read the entire field */ - if ((datum_count == 1) && - (obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) { - /* 1) Shift the valid data bits down to start at bit 0 */ + for (i = 0; i < datum_count; i++) { + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + &this_raw_datum, ACPI_READ); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset); + /* We might actually be done if the request fits in one datum */ - /* 2) Mask off any upper unused bits (bits not part of the field) */ + if ((datum_count == 1) && + (obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) { + /* 1) Shift the valid data bits down to start at bit 0 */ - if (obj_desc->common_field.end_buffer_valid_bits) { - merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); - } + merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset); - /* Store the datum to the caller buffer */ + /* 2) Mask off any upper unused bits (bits not part of the field) */ - acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length, - obj_desc->common_field.access_byte_width, datum_offset); + if (obj_desc->common_field.end_buffer_valid_bits) { + merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); + } - return_ACPI_STATUS (AE_OK); - } + /* Store the datum to the caller buffer */ + acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length, + obj_desc->common_field.access_byte_width, buffer_datum_offset); - /* We need to get more raw data to complete one or more field data */ + return_ACPI_STATUS (AE_OK); + } - while (datum_offset < datum_count) { - field_datum_byte_offset += obj_desc->common_field.access_byte_width; + /* Special handling for the last datum to ignore extra bits */ - /* - * If the field is aligned on a byte boundary, we don't want - * to perform a final read, since this would potentially read - * past the end of the region. - * - * We could just split the aligned and non-aligned cases since the - * aligned case is so very simple, but this would require more code. - */ - if ((obj_desc->common_field.start_field_bit_offset != 0) || - ((obj_desc->common_field.start_field_bit_offset == 0) && - (datum_offset < (datum_count -1)))) { + if ((i >= (datum_count -1)) && + (obj_desc->common_field.end_field_valid_bits)) { /* - * Get the next raw datum, it contains some or all bits - * of the current field datum + * This is the last iteration of the loop. We need to clear + * any unused bits (bits that are not part of this field) before + * we store the final merged datum into the caller buffer. */ - status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, - &this_raw_datum, ACPI_READ); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + this_raw_datum &= + ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); } /* @@ -891,48 +891,48 @@ if (obj_desc->common_field.start_field_bit_offset == 0) { /* Field is not skewed and we can just copy the datum */ - merged_datum = previous_raw_datum; + acpi_ex_set_buffer_datum (this_raw_datum, buffer, buffer_length, + obj_desc->common_field.access_byte_width, buffer_datum_offset); + buffer_datum_offset++; } else { - /* - * Put together the appropriate bits of the two raw data to make a - * single complete field datum - * - * 1) Normalize the first datum down to bit 0 - */ - merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset); + /* Not aligned -- on the first iteration, just save the datum */ - /* 2) Insert the second datum "above" the first datum */ - - merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits); - - if ((datum_offset >= (datum_count -1))) { + if (i != 0) { /* - * This is the last iteration of the loop. We need to clear - * any unused bits (bits that are not part of this field) that - * came from the last raw datum before we store the final - * merged datum into the caller buffer. + * Put together the appropriate bits of the two raw data to make a + * single complete field datum + * + * 1) Normalize the first datum down to bit 0 */ - if (obj_desc->common_field.end_buffer_valid_bits) { - merged_datum &= - ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); - } + merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset); + + /* 2) Insert the second datum "above" the first datum */ + + merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits); + + acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length, + obj_desc->common_field.access_byte_width, buffer_datum_offset); + buffer_datum_offset++; } + + /* + * Save the raw datum that was just acquired since it may contain bits + * of the *next* field datum + */ + previous_raw_datum = this_raw_datum; } - /* - * Store the merged field datum in the caller's buffer, according to - * the granularity of the field (size of each datum). - */ - acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length, - obj_desc->common_field.access_byte_width, datum_offset); + field_datum_byte_offset += obj_desc->common_field.access_byte_width; + } - /* - * Save the raw datum that was just acquired since it may contain bits - * of the *next* field datum. Update offsets - */ - previous_raw_datum = this_raw_datum; - datum_offset++; + /* For non-aligned case, there is one last datum to insert */ + + if (obj_desc->common_field.start_field_bit_offset != 0) { + merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset); + + acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length, + obj_desc->common_field.access_byte_width, buffer_datum_offset); } return_ACPI_STATUS (AE_OK); diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exmisc.c linux-2.6.2-rc3/drivers/acpi/executer/exmisc.c --- linux-2.6.2-rc2/drivers/acpi/executer/exmisc.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exmisc.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,8 +121,8 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid descriptor type %X in %p\n", - ACPI_GET_DESCRIPTOR_TYPE (obj_desc), obj_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p has invalid descriptor [%s]\n", + obj_desc, acpi_ut_get_descriptor_name (obj_desc))); return_ACPI_STATUS (AE_TYPE); } @@ -139,7 +139,7 @@ *return_desc = reference_obj; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n", - obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc)); + obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc)); return_ACPI_STATUS (AE_OK); } diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exmutex.c linux-2.6.2-rc3/drivers/acpi/executer/exmutex.c --- linux-2.6.2-rc2/drivers/acpi/executer/exmutex.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exmutex.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -159,7 +159,7 @@ if (!walk_state->thread) { ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n", - obj_desc->mutex.node->name.ascii)); + acpi_ut_get_node_name (obj_desc->mutex.node))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -169,7 +169,7 @@ */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", - obj_desc->mutex.node->name.ascii)); + acpi_ut_get_node_name (obj_desc->mutex.node))); return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } @@ -242,7 +242,7 @@ if (!obj_desc->mutex.owner_thread) { ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n", - obj_desc->mutex.node->name.ascii)); + acpi_ut_get_node_name (obj_desc->mutex.node))); return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); } @@ -250,7 +250,7 @@ if (!walk_state->thread) { ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n", - obj_desc->mutex.node->name.ascii)); + acpi_ut_get_node_name (obj_desc->mutex.node))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -260,7 +260,7 @@ ACPI_REPORT_ERROR (( "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, - obj_desc->mutex.node->name.ascii, + acpi_ut_get_node_name (obj_desc->mutex.node), obj_desc->mutex.owner_thread->thread_id)); return_ACPI_STATUS (AE_AML_NOT_OWNER); } @@ -271,7 +271,7 @@ */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], incorrect sync_level\n", - obj_desc->mutex.node->name.ascii)); + acpi_ut_get_node_name (obj_desc->mutex.node))); return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exnames.c linux-2.6.2-rc3/drivers/acpi/executer/exnames.c --- linux-2.6.2-rc2/drivers/acpi/executer/exnames.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exnames.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exoparg1.c linux-2.6.2-rc3/drivers/acpi/executer/exoparg1.c --- linux-2.6.2-rc2/drivers/acpi/executer/exoparg1.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exoparg1.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -351,8 +351,7 @@ if (digit > 0) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Integer too large to convert to BCD: %8.8X%8.8X\n", - ACPI_HIDWORD(operand[0]->integer.value), - ACPI_LODWORD(operand[0]->integer.value))); + ACPI_FORMAT_UINT64 (operand[0]->integer.value))); status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; } diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exoparg2.c linux-2.6.2-rc3/drivers/acpi/executer/exoparg2.c --- linux-2.6.2-rc2/drivers/acpi/executer/exoparg2.c 2004-01-08 22:59:41.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exoparg2.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exoparg3.c linux-2.6.2-rc3/drivers/acpi/executer/exoparg3.c --- linux-2.6.2-rc2/drivers/acpi/executer/exoparg3.c 2004-01-08 22:59:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exoparg3.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -101,15 +101,14 @@ switch (walk_state->opcode) { - case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", - (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, + (u32) operand[0]->integer.value, + (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); - fatal = ACPI_MEM_ALLOCATE (sizeof (struct acpi_signal_fatal_info)); if (fatal) { fatal->type = (u32) operand[0]->integer.value; diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exoparg6.c linux-2.6.2-rc3/drivers/acpi/executer/exoparg6.c --- linux-2.6.2-rc2/drivers/acpi/executer/exoparg6.c 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exoparg6.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exprep.c linux-2.6.2-rc3/drivers/acpi/executer/exprep.c --- linux-2.6.2-rc2/drivers/acpi/executer/exprep.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exprep.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -351,7 +351,7 @@ */ nearest_byte_address = ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position); - obj_desc->common_field.base_byte_offset = + obj_desc->common_field.base_byte_offset = (u32) ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment); /* @@ -539,7 +539,7 @@ acpi_ns_get_type (info->field_node)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n", - info->field_node, info->field_node->name.ascii, obj_desc)); + info->field_node, acpi_ut_get_node_name (info->field_node), obj_desc)); /* Remove local reference to the object */ diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exregion.c linux-2.6.2-rc3/drivers/acpi/executer/exregion.c --- linux-2.6.2-rc2/drivers/acpi/executer/exregion.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exregion.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -161,7 +161,7 @@ (void **) &mem_info->mapped_logical_address); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n", - ACPI_HIDWORD (address), ACPI_LODWORD (address), (u32) window_size)); + ACPI_FORMAT_UINT64 (address), (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS (status); } @@ -180,8 +180,8 @@ ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "system_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, - ACPI_HIDWORD (address), ACPI_LODWORD (address))); + "system_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, + ACPI_FORMAT_UINT64 (address))); /* * Perform the memory read or write @@ -290,8 +290,8 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, - ACPI_HIDWORD (address), ACPI_LODWORD (address))); + "system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, + ACPI_FORMAT_UINT64 (address))); /* Decode the function parameter */ diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exresnte.c linux-2.6.2-rc3/drivers/acpi/executer/exresnte.c --- linux-2.6.2-rc2/drivers/acpi/executer/exresnte.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exresnte.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exresolv.c linux-2.6.2-rc3/drivers/acpi/executer/exresolv.c --- linux-2.6.2-rc2/drivers/acpi/executer/exresolv.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exresolv.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -349,6 +349,8 @@ /* All "References" point to a NS node */ if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { + ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", + node, acpi_ut_get_descriptor_name (node))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -399,7 +401,9 @@ /* All "References" point to a NS node */ if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { - return_ACPI_STATUS (AE_AML_INTERNAL); + ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", + node, acpi_ut_get_descriptor_name (node))); + return_ACPI_STATUS (AE_AML_INTERNAL); } /* Get the attached object */ diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exresop.c linux-2.6.2-rc3/drivers/acpi/executer/exresop.c --- linux-2.6.2-rc2/drivers/acpi/executer/exresop.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exresop.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -247,8 +247,8 @@ /* Invalid descriptor */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Bad descriptor type %X in Obj %p\n", - ACPI_GET_DESCRIPTOR_TYPE (obj_desc), obj_desc)); + "Invalid descriptor %p [%s]\n", + obj_desc, acpi_ut_get_descriptor_name (obj_desc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exstore.c linux-2.6.2-rc3/drivers/acpi/executer/exstore.c --- linux-2.6.2-rc2/drivers/acpi/executer/exstore.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exstore.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -190,8 +190,7 @@ case ACPI_TYPE_INTEGER: ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n", - ACPI_HIDWORD (source_desc->integer.value), - ACPI_LODWORD (source_desc->integer.value))); + ACPI_FORMAT_UINT64 (source_desc->integer.value))); break; diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exstoren.c linux-2.6.2-rc3/drivers/acpi/executer/exstoren.c --- linux-2.6.2-rc2/drivers/acpi/executer/exstoren.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exstoren.c 2004-01-30 18:49:20.000000000 -0800 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exstorob.c linux-2.6.2-rc3/drivers/acpi/executer/exstorob.c --- linux-2.6.2-rc2/drivers/acpi/executer/exstorob.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exstorob.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exsystem.c linux-2.6.2-rc3/drivers/acpi/executer/exsystem.c --- linux-2.6.2-rc2/drivers/acpi/executer/exsystem.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exsystem.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,11 +111,16 @@ * * FUNCTION: acpi_ex_system_do_stall * - * PARAMETERS: how_long - The amount of time to stall + * PARAMETERS: how_long - The amount of time to stall, + * in microseconds * * RETURN: Status * * DESCRIPTION: Suspend running thread for specified amount of time. + * Note: ACPI specification requires that Stall() does not + * relinquish the processor, and delays longer than 100 usec + * should use Sleep() instead. We allow stalls up to 255 usec + * for compatibility with other interpreters and existing BIOSs. * ******************************************************************************/ @@ -129,12 +134,15 @@ ACPI_FUNCTION_ENTRY (); - if (how_long > 100) /* 100 microseconds */ { + if (how_long > 255) /* 255 microseconds */ { /* - * Longer than 100 usec, use sleep instead - * (according to ACPI specification) + * Longer than 255 usec, this is an error + * + * (ACPI specifies 100 usec as max, but this gives some slack in + * order to support existing BIOSs) */ - status = acpi_ex_system_do_suspend ((how_long / 1000) + 1); + ACPI_REPORT_ERROR (("Stall: Time parameter is too large (%d)\n", how_long)); + status = AE_AML_OPERAND_VALUE; } else { acpi_os_stall (how_long); @@ -148,7 +156,8 @@ * * FUNCTION: acpi_ex_system_do_suspend * - * PARAMETERS: how_long - The amount of time to suspend + * PARAMETERS: how_long - The amount of time to suspend, + * in milliseconds * * RETURN: None * diff -urN linux-2.6.2-rc2/drivers/acpi/executer/exutils.c linux-2.6.2-rc3/drivers/acpi/executer/exutils.c --- linux-2.6.2-rc2/drivers/acpi/executer/exutils.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/executer/exutils.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/fan.c linux-2.6.2-rc3/drivers/acpi/fan.c --- linux-2.6.2-rc2/drivers/acpi/fan.c 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/fan.c 2004-01-30 18:49:20.000000000 -0800 @@ -71,7 +71,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_fan_dir = NULL; +struct proc_dir_entry *acpi_fan_dir; static int diff -urN linux-2.6.2-rc2/drivers/acpi/hardware/hwacpi.c linux-2.6.2-rc3/drivers/acpi/hardware/hwacpi.c --- linux-2.6.2-rc2/drivers/acpi/hardware/hwacpi.c 2004-01-08 22:59:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/hardware/hwacpi.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -119,7 +119,7 @@ * system does not support mode transition. */ if (!acpi_gbl_FADT->smi_cmd) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No SMI_CMD in FADT, mode transition failed.\n")); + ACPI_REPORT_ERROR (("No SMI_CMD in FADT, mode transition failed.\n")); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } @@ -131,7 +131,7 @@ * transitions are not supported. */ if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No mode transition supported in this system.\n")); + ACPI_REPORT_ERROR (("No ACPI mode transition supported in this system (enable/disable both zero)\n")); return_ACPI_STATUS (AE_OK); } @@ -162,6 +162,7 @@ } if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not write mode change, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } @@ -171,18 +172,16 @@ */ retry = 3000; while (retry) { - status = AE_NO_HARDWARE_RESPONSE; - if (acpi_hw_get_mode() == mode) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode)); - status = AE_OK; - break; + return_ACPI_STATUS (AE_OK); } acpi_os_stall(1000); retry--; } - return_ACPI_STATUS (status); + ACPI_REPORT_ERROR (("Hardware never changed modes\n")); + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } diff -urN linux-2.6.2-rc2/drivers/acpi/hardware/hwgpe.c linux-2.6.2-rc3/drivers/acpi/hardware/hwgpe.c --- linux-2.6.2-rc2/drivers/acpi/hardware/hwgpe.c 2004-01-08 22:59:05.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/hardware/hwgpe.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -348,17 +348,14 @@ struct acpi_gpe_block_info *gpe_block) { u32 i; - struct acpi_gpe_register_info *gpe_register_info; acpi_status status; - /* Get the register info for the entire GPE block */ - - gpe_register_info = gpe_block->register_info; - /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Disable all GPEs in this register */ + status = acpi_hw_low_level_write (8, 0x00, &gpe_block->register_info[i].enable_address); if (ACPI_FAILURE (status)) { @@ -389,17 +386,14 @@ struct acpi_gpe_block_info *gpe_block) { u32 i; - struct acpi_gpe_register_info *gpe_register_info; acpi_status status; - /* Get the register info for the entire GPE block */ - - gpe_register_info = gpe_block->register_info; - /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Clear all GPEs in this register */ + status = acpi_hw_low_level_write (8, 0xFF, &gpe_block->register_info[i].status_address); if (ACPI_FAILURE (status)) { diff -urN linux-2.6.2-rc2/drivers/acpi/hardware/hwregs.c linux-2.6.2-rc3/drivers/acpi/hardware/hwregs.c --- linux-2.6.2-rc2/drivers/acpi/hardware/hwregs.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/hardware/hwregs.c 2004-01-30 18:49:20.000000000 -0800 @@ -7,7 +7,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -418,16 +418,14 @@ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", register_value, - ACPI_HIDWORD (acpi_gbl_FADT->xpm2_cnt_blk.address), - ACPI_LODWORD (acpi_gbl_FADT->xpm2_cnt_blk.address))); + ACPI_FORMAT_UINT64 (acpi_gbl_FADT->xpm2_cnt_blk.address))); ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", register_value, - ACPI_HIDWORD (acpi_gbl_FADT->xpm2_cnt_blk.address), - ACPI_LODWORD (acpi_gbl_FADT->xpm2_cnt_blk.address))); + ACPI_FORMAT_UINT64 (acpi_gbl_FADT->xpm2_cnt_blk.address))); status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM2_CONTROL, (u8) (register_value)); @@ -763,8 +761,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", *value, width, - ACPI_HIDWORD (reg->address), - ACPI_LODWORD (reg->address), + ACPI_FORMAT_UINT64 (reg->address), acpi_ut_get_region_name (reg->address_space_id))); return (status); @@ -850,8 +847,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", value, width, - ACPI_HIDWORD (reg->address), - ACPI_LODWORD (reg->address), + ACPI_FORMAT_UINT64 (reg->address), acpi_ut_get_region_name (reg->address_space_id))); return (status); diff -urN linux-2.6.2-rc2/drivers/acpi/hardware/hwsleep.c linux-2.6.2-rc3/drivers/acpi/hardware/hwsleep.c --- linux-2.6.2-rc2/drivers/acpi/hardware/hwsleep.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/hardware/hwsleep.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -181,6 +181,13 @@ return_ACPI_STATUS (status); } + /* Set the system indicators to show the desired sleep state. */ + + status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status))); + } + return_ACPI_STATUS (AE_OK); } @@ -220,30 +227,31 @@ return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } - sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A); sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE); - /* Clear wake status */ + if (sleep_state != ACPI_STATE_S5) { + /* Clear wake status */ - status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - /* Disable BM arbitration */ + /* Disable BM arbitration */ - status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - status = acpi_hw_disable_non_wakeup_gpes(); + status = acpi_hw_disable_non_wakeup_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -266,6 +274,11 @@ PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); + /* + * We split the writes of SLP_TYP and SLP_EN to workaround + * poorly implemented hardware. + */ + /* Write #1: fill in SLP_TYP data */ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); @@ -297,13 +310,15 @@ return_ACPI_STATUS (status); } - /* - * Wait a second, then try again. This is to get S4/5 to work on all machines. - */ if (sleep_state > ACPI_STATE_S3) { /* + * We wanted to sleep > S3, but it didn't happen (by virtue of the fact that + * we are still executing!) + * + * Wait ten seconds, then try again. This is to get S4/S5 to work on all machines. + * * We wait so long to allow chipsets that poll this reg very slowly to - * still read the right value. Ideally, this entire block would go + * still read the right value. Ideally, this block would go * away entirely. */ acpi_os_stall (10000000); @@ -354,12 +369,23 @@ ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios"); - acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); - acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); - acpi_hw_disable_non_wakeup_gpes(); + status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_disable_non_wakeup_gpes (); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - ACPI_FLUSH_CPU_CACHE(); + ACPI_FLUSH_CPU_CACHE (); status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (u32) acpi_gbl_FADT->S4bios_req, 8); @@ -389,16 +415,56 @@ acpi_status acpi_leave_sleep_state ( - u8 sleep_state) + u8 sleep_state) { - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + u32 PM1Acontrol; + u32 PM1Bcontrol; ACPI_FUNCTION_TRACE ("acpi_leave_sleep_state"); + /* + * Set SLP_TYPE and SLP_EN to state S0. + * This is unclear from the ACPI Spec, but it is required + * by some machines. + */ + status = acpi_get_sleep_type_data (ACPI_STATE_S0, + &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b); + if (ACPI_SUCCESS (status)) { + sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE); + + /* Get current value of PM1A control */ + + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + if (ACPI_SUCCESS (status)) { + /* Clear SLP_EN and SLP_TYP fields */ + + PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info->access_bit_mask); + PM1Bcontrol = PM1Acontrol; + + /* Insert SLP_TYP bits */ + + PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); + PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); + + /* Just ignore any errors */ + + (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); + (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + } + } + /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; @@ -407,12 +473,17 @@ arg_list.count = 1; arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; /* Ignore any errors from these methods */ + arg.integer.value = 0; + status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status))); + } + + arg.integer.value = sleep_state; status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status))); @@ -425,13 +496,13 @@ /* _WAK returns stuff - do we want to look at it? */ - status = acpi_hw_enable_non_wakeup_gpes(); + status = acpi_hw_enable_non_wakeup_gpes (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* Disable BM arbitration */ - status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK); + /* Enable BM arbitration */ + status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK); return_ACPI_STATUS (status); } diff -urN linux-2.6.2-rc2/drivers/acpi/hardware/hwtimer.c linux-2.6.2-rc3/drivers/acpi/hardware/hwtimer.c --- linux-2.6.2-rc2/drivers/acpi/hardware/hwtimer.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/hardware/hwtimer.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsaccess.c linux-2.6.2-rc3/drivers/acpi/namespace/nsaccess.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsaccess.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsaccess.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -314,8 +314,8 @@ else { prefix_node = scope_info->scope.node; if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "[%p] Not a namespace node\n", - prefix_node)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p Not a namespace node [%s]\n", + prefix_node, acpi_ut_get_descriptor_name (prefix_node))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -379,7 +379,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching relative to prefix scope [%4.4s] (%p)\n", - prefix_node->name.ascii, prefix_node)); + acpi_ut_get_node_name (prefix_node), prefix_node)); /* * Handle multiple Parent Prefixes (carat) by just getting @@ -413,7 +413,7 @@ if (search_parent_flag == ACPI_NS_NO_UPSEARCH) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Search scope is [%4.4s], path has %d carat(s)\n", - this_node->name.ascii, num_carats)); + acpi_ut_get_node_name (this_node), num_carats)); } } diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsalloc.c linux-2.6.2-rc3/drivers/acpi/namespace/nsalloc.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsalloc.c 2004-01-08 22:59:41.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsalloc.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -271,7 +271,7 @@ * alphabetic placement. */ previous_child_node = NULL; - while (acpi_ns_compare_names (child_node->name.ascii, node->name.ascii) < 0) { + while (acpi_ns_compare_names (acpi_ut_get_node_name (child_node), acpi_ut_get_node_name (node)) < 0) { if (child_node->flags & ANOBJ_END_OF_PEER_LIST) { /* Last peer; Clear end-of-list flag */ @@ -335,8 +335,9 @@ node->type = (u8) type; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s (%s) added to %4.4s (%s) %p at %p\n", - node->name.ascii, acpi_ut_get_type_name (node->type), - parent_node->name.ascii, acpi_ut_get_type_name (parent_node->type), parent_node, node)); + acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), + acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type), + parent_node, node)); /* * Increment the reference count(s) of all parents up to diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsdump.c linux-2.6.2-rc3/drivers/acpi/namespace/nsdump.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsdump.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsdump.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,8 +50,8 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME ("nsdump") -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /******************************************************************************* * @@ -76,7 +76,7 @@ return; } - /* Print the entire name */ + /* Print the entire name */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[")); @@ -205,7 +205,7 @@ * Now we can print out the pertinent information */ acpi_os_printf ("%4.4s %-12s %p ", - this_node->name.ascii, acpi_ut_get_type_name (type), this_node); + acpi_ut_get_node_name (this_node), acpi_ut_get_type_name (type), this_node); dbg_level = acpi_dbg_level; acpi_dbg_level = 0; @@ -250,8 +250,7 @@ case ACPI_TYPE_INTEGER: acpi_os_printf ("= %8.8X%8.8X\n", - ACPI_HIDWORD (obj_desc->integer.value), - ACPI_LODWORD (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; @@ -302,8 +301,7 @@ acpi_os_printf ("[%s]", acpi_ut_get_region_name (obj_desc->region.space_id)); if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n", - ACPI_HIDWORD (obj_desc->region.address), - ACPI_LODWORD (obj_desc->region.address), + ACPI_FORMAT_UINT64 (obj_desc->region.address), obj_desc->region.length); } else { @@ -324,7 +322,7 @@ if (obj_desc->buffer_field.buffer_obj && obj_desc->buffer_field.buffer_obj->buffer.node) { acpi_os_printf ("Buf [%4.4s]", - obj_desc->buffer_field.buffer_obj->buffer.node->name.ascii); + acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node)); } break; @@ -332,29 +330,29 @@ case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf ("Rgn [%4.4s]", - obj_desc->common_field.region_obj->region.node->name.ascii); + acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: acpi_os_printf ("Rgn [%4.4s] Bnk [%4.4s]", - obj_desc->common_field.region_obj->region.node->name.ascii, - obj_desc->bank_field.bank_obj->common_field.node->name.ascii); + acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node), + acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node)); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: acpi_os_printf ("Idx [%4.4s] Dat [%4.4s]", - obj_desc->index_field.index_obj->common_field.node->name.ascii, - obj_desc->index_field.data_obj->common_field.node->name.ascii); + acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node), + acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node)); break; case ACPI_TYPE_LOCAL_ALIAS: - acpi_os_printf ("Target %4.4s (%p)\n", ((struct acpi_namespace_node *) obj_desc)->name.ascii, obj_desc); + acpi_os_printf ("Target %4.4s (%p)\n", acpi_ut_get_node_name (obj_desc), obj_desc); break; default: @@ -371,7 +369,7 @@ case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_os_printf ("Off %.2X Len %.2X Acc %.2hd\n", + acpi_os_printf (" Off %.3X Len %.2X Acc %.2hd\n", (obj_desc->common_field.base_byte_offset * 8) + obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.bit_length, @@ -408,8 +406,8 @@ case ACPI_TYPE_INTEGER: - acpi_os_printf (" N:%X%X\n", ACPI_HIDWORD(obj_desc->integer.value), - ACPI_LODWORD(obj_desc->integer.value)); + acpi_os_printf (" I:%8.8X8.8%X\n", + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; case ACPI_TYPE_STRING: @@ -485,7 +483,8 @@ default: - acpi_os_printf ("(String or Buffer ptr - not an object descriptor)\n"); + acpi_os_printf ("(String or Buffer ptr - not an object descriptor) [%s]\n", + acpi_ut_get_descriptor_name (obj_desc)); bytes_to_dump = 16; break; } @@ -581,7 +580,6 @@ info.owner_id = owner_id; info.display_type = display_type; - (void) acpi_ns_walk_namespace (type, start_handle, max_depth, ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object, (void *) &info, NULL); @@ -628,7 +626,6 @@ ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n")); } - acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth, ACPI_UINT32_MAX, search_handle); return_VOID; diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsdumpdv.c linux-2.6.2-rc3/drivers/acpi/namespace/nsdumpdv.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsdumpdv.c 2004-01-08 22:59:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsdumpdv.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,7 +93,7 @@ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", info->hardware_id.value, - ACPI_HIDWORD (info->address), ACPI_LODWORD (info->address), + ACPI_FORMAT_UINT64 (info->address), info->current_status)); ACPI_MEM_FREE (info); } diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nseval.c linux-2.6.2-rc3/drivers/acpi/namespace/nseval.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nseval.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nseval.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsinit.c linux-2.6.2-rc3/drivers/acpi/namespace/nsinit.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsinit.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsinit.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -144,10 +144,17 @@ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Executing all Device _STA and_INI methods:")); - /* Walk namespace for all objects of type Device */ + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Walk namespace for all objects of type Device or Processor */ - status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL); + + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n", @@ -290,7 +297,8 @@ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not execute arguments for [%4.4s] (%s), %s\n", - node->name.ascii, acpi_ut_get_type_name (type), acpi_format_exception (status))); + acpi_ut_get_node_name (node), acpi_ut_get_type_name (type), + acpi_format_exception (status))); } /* Print a dot for each object unless we are going to print the entire pathname */ @@ -338,45 +346,48 @@ ACPI_FUNCTION_TRACE ("ns_init_one_device"); - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); - } - - info->device_count++; - - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - node = acpi_ns_map_handle_to_node (obj_handle); if (!node) { - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_BAD_PARAMETER); } - status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + /* + * We will run _STA/_INI on Devices and Processors only + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR)) { + return_ACPI_STATUS (AE_OK); } + if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && (!(acpi_dbg_level & ACPI_LV_INFO))) { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); + } + + info->device_count++; + /* * Run _STA to determine if we can run _INI on the device. */ ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, node, "_STA")); status = acpi_ut_execute_STA (node, &flags); + if (ACPI_FAILURE (status)) { - /* Ignore error and move on to next device */ + if (node->type == ACPI_TYPE_DEVICE) { + /* Ignore error and move on to next device */ - return_ACPI_STATUS (AE_OK); - } + return_ACPI_STATUS (AE_OK); + } - info->num_STA++; + /* _STA is not required for Processor objects */ + } + else { + info->num_STA++; - if (!(flags & 0x01)) { - /* don't look at children of a not present device */ + if (!(flags & 0x01)) { + /* Don't look at children of a not present device */ - return_ACPI_STATUS(AE_CTRL_DEPTH); + return_ACPI_STATUS(AE_CTRL_DEPTH); + } } /* diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsload.c linux-2.6.2-rc3/drivers/acpi/namespace/nsload.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsload.c 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsload.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsnames.c linux-2.6.2-rc3/drivers/acpi/namespace/nsnames.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsnames.c 2004-01-08 23:00:13.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsnames.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsobject.c linux-2.6.2-rc3/drivers/acpi/namespace/nsobject.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsobject.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsobject.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -104,7 +104,8 @@ if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { /* Not a name handle */ - ACPI_REPORT_ERROR (("ns_attach_object: Invalid handle\n")); + ACPI_REPORT_ERROR (("ns_attach_object: Invalid handle %p [%s]\n", + node, acpi_ut_get_descriptor_name (node))); return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -151,7 +152,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", - obj_desc, node, node->name.ascii)); + obj_desc, node, acpi_ut_get_node_name (node))); /* Detach an existing attached object if present */ @@ -234,7 +235,7 @@ node->type = ACPI_TYPE_ANY; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", - node, node->name.ascii, obj_desc)); + node, acpi_ut_get_node_name (node), obj_desc)); /* Remove one reference on the object (and all subobjects) */ diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsparse.c linux-2.6.2-rc3/drivers/acpi/namespace/nsparse.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsparse.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsparse.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nssearch.c linux-2.6.2-rc3/drivers/acpi/namespace/nssearch.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nssearch.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nssearch.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -119,7 +119,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", (char *) &target_name, acpi_ut_get_type_name (next_node->type), - next_node, node->name.ascii, node)); + next_node, acpi_ut_get_node_name (node), node)); *return_node = next_node; return_ACPI_STATUS (AE_OK); @@ -145,7 +145,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", (char *) &target_name, acpi_ut_get_type_name (type), - node->name.ascii, node, node->child)); + acpi_ut_get_node_name (node), node, node->child)); return_ACPI_STATUS (AE_NOT_FOUND); } diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsutils.c linux-2.6.2-rc3/drivers/acpi/namespace/nsutils.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsutils.c 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsutils.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -977,8 +977,8 @@ parent_node = acpi_ns_get_parent_node (child_node); if (parent_node) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Parent of %p [%4.4s] is %p [%4.4s]\n", - child_node, child_node->name.ascii, - parent_node, parent_node->name.ascii)); + child_node, acpi_ut_get_node_name (child_node), + parent_node, acpi_ut_get_node_name (parent_node))); if (parent_node->name.integer) { return_VALUE ((acpi_name) parent_node->name.integer); @@ -986,7 +986,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "unable to find parent of %p (%4.4s)\n", - child_node, child_node->name.ascii)); + child_node, acpi_ut_get_node_name (child_node))); } return_VALUE (ACPI_UNKNOWN_NAME); diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nswalk.c linux-2.6.2-rc3/drivers/acpi/namespace/nswalk.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nswalk.c 2004-01-08 23:00:13.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nswalk.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsxfeval.c linux-2.6.2-rc3/drivers/acpi/namespace/nsxfeval.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsxfeval.c 2004-01-08 23:00:12.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsxfeval.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsxfname.c linux-2.6.2-rc3/drivers/acpi/namespace/nsxfname.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsxfname.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsxfname.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -199,7 +199,7 @@ /* Just copy the ACPI name from the Node and zero terminate it */ - ACPI_STRNCPY (buffer->pointer, node->name.ascii, + ACPI_STRNCPY (buffer->pointer, acpi_ut_get_node_name (node), ACPI_NAME_SIZE); ((char *) buffer->pointer) [ACPI_NAME_SIZE] = 0; status = AE_OK; diff -urN linux-2.6.2-rc2/drivers/acpi/namespace/nsxfobj.c linux-2.6.2-rc3/drivers/acpi/namespace/nsxfobj.c --- linux-2.6.2-rc2/drivers/acpi/namespace/nsxfobj.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/namespace/nsxfobj.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/osl.c linux-2.6.2-rc3/drivers/acpi/osl.c --- linux-2.6.2-rc2/drivers/acpi/osl.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/osl.c 2004-01-30 18:49:20.000000000 -0800 @@ -59,13 +59,13 @@ #ifdef ENABLE_DEBUGGER #include /* stuff for debugger support */ -int acpi_in_debugger = 0; +int acpi_in_debugger; extern char line_buf[80]; #endif /*ENABLE_DEBUGGER*/ -static int acpi_irq_irq = 0; -static OSD_HANDLER acpi_irq_handler = NULL; -static void *acpi_irq_context = NULL; +static int acpi_irq_irq; +static OSD_HANDLER acpi_irq_handler; +static void *acpi_irq_context; acpi_status acpi_os_initialize(void) @@ -257,13 +257,13 @@ return AE_OK; } #endif - acpi_irq_irq = irq; acpi_irq_handler = handler; acpi_irq_context = context; if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); return AE_NOT_ACQUIRED; } + acpi_irq_irq = irq; return AE_OK; } @@ -271,12 +271,13 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) { - if (acpi_irq_handler) { + if (irq) { #ifdef CONFIG_IA64 irq = acpi_irq_to_vector(irq); #endif free_irq(irq, acpi_irq); acpi_irq_handler = NULL; + acpi_irq_irq = 0; } return AE_OK; diff -urN linux-2.6.2-rc2/drivers/acpi/parser/psargs.c linux-2.6.2-rc3/drivers/acpi/parser/psargs.c --- linux-2.6.2-rc2/drivers/acpi/parser/psargs.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/psargs.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -490,7 +490,7 @@ acpi_ps_get_next_field ( struct acpi_parse_state *parser_state) { - u32 aml_offset = ACPI_PTR_DIFF (parser_state->aml, + u32 aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); union acpi_parse_object *field; u16 opcode; @@ -677,7 +677,7 @@ /* Fill in bytelist data */ - arg->common.value.size = ACPI_PTR_DIFF (parser_state->pkg_end, + arg->common.value.size = (u32) ACPI_PTR_DIFF (parser_state->pkg_end, parser_state->aml); arg->named.data = parser_state->aml; diff -urN linux-2.6.2-rc2/drivers/acpi/parser/psopcode.c linux-2.6.2-rc3/drivers/acpi/parser/psopcode.c --- linux-2.6.2-rc2/drivers/acpi/parser/psopcode.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/psopcode.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/parser/psparse.c linux-2.6.2-rc3/drivers/acpi/parser/psparse.c --- linux-2.6.2-rc2/drivers/acpi/parser/psparse.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/psparse.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -498,7 +498,7 @@ if (!op) { /* Get the next opcode from the AML stream */ - walk_state->aml_offset = ACPI_PTR_DIFF (parser_state->aml, + walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); walk_state->opcode = acpi_ps_peek_opcode (parser_state); @@ -710,7 +710,7 @@ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && !walk_state->arg_count) { - walk_state->aml_offset = ACPI_PTR_DIFF (parser_state->aml, + walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); status = acpi_ps_get_next_arg (walk_state, parser_state, GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg); diff -urN linux-2.6.2-rc2/drivers/acpi/parser/psscope.c linux-2.6.2-rc3/drivers/acpi/parser/psscope.c --- linux-2.6.2-rc2/drivers/acpi/parser/psscope.c 2004-01-08 22:59:06.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/psscope.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/parser/pstree.c linux-2.6.2-rc3/drivers/acpi/parser/pstree.c --- linux-2.6.2-rc2/drivers/acpi/parser/pstree.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/pstree.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/parser/psutils.c linux-2.6.2-rc3/drivers/acpi/parser/psutils.c --- linux-2.6.2-rc2/drivers/acpi/parser/psutils.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/psutils.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/parser/pswalk.c linux-2.6.2-rc3/drivers/acpi/parser/pswalk.c --- linux-2.6.2-rc2/drivers/acpi/parser/pswalk.c 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/pswalk.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/parser/psxface.c linux-2.6.2-rc3/drivers/acpi/parser/psxface.c --- linux-2.6.2-rc2/drivers/acpi/parser/psxface.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/parser/psxface.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -127,7 +127,8 @@ op = acpi_ps_create_scope_op (); if (!op) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup1; } /* @@ -142,20 +143,24 @@ walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, NULL, NULL, NULL); if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { - acpi_ds_delete_walk_state (walk_state); - return_ACPI_STATUS (status); + goto cleanup3; } /* Parse the AML */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); + if (ACPI_FAILURE (status)) { + goto cleanup1; /* Walk state is already deleted */ + + } /* * 2) Execute the method. Performs second pass parse simultaneously @@ -168,7 +173,8 @@ op = acpi_ps_create_scope_op (); if (!op) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup1; } /* Init new op with the method name and pointer back to the NS node */ @@ -180,22 +186,30 @@ walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, params, return_obj_desc, 3); if (ACPI_FAILURE (status)) { - acpi_ds_delete_walk_state (walk_state); - return_ACPI_STATUS (status); + goto cleanup3; } /* * The walk of the parse tree is where we actually execute the method */ status = acpi_ps_parse_aml (walk_state); + goto cleanup2; /* Walk state already deleted */ + + +cleanup3: + acpi_ds_delete_walk_state (walk_state); + +cleanup2: acpi_ps_delete_parse_tree (op); +cleanup1: if (params) { /* Take away the extra reference that we gave the parameters above */ @@ -206,6 +220,10 @@ } } + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + /* * If the method has returned an object, signal this to the caller with * a control exception code diff -urN linux-2.6.2-rc2/drivers/acpi/pci_link.c linux-2.6.2-rc3/drivers/acpi/pci_link.c --- linux-2.6.2-rc2/drivers/acpi/pci_link.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/pci_link.c 2004-01-30 18:49:20.000000000 -0800 @@ -99,7 +99,7 @@ void *context) { struct acpi_pci_link *link = (struct acpi_pci_link *) context; - int i = 0; + u32 i = 0; ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible"); @@ -294,7 +294,10 @@ if (!link->irq.active) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n")); - printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), acpi_device_bid(link->device)); + printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for" + "device (%s [%s]).\n", irq, + acpi_device_name(link->device), + acpi_device_bid(link->device)); link->irq.active = irq; } @@ -429,30 +432,67 @@ PCI Link IRQ Management -------------------------------------------------------------------------- */ -#define ACPI_MAX_IRQS 256 -#define ACPI_MAX_ISA_IRQ 16 - /* - * IRQ penalties are used to promote PCI IRQ balancing. We set each ISA- - * possible IRQ (0-15) with a default penalty relative to its feasibility - * for PCI's use: + * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt + * Link Devices to move the PIRQs around to minimize sharing. + * + * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs + * that the BIOS has already set to active. This is necessary because + * ACPI has no automatic means of knowing what ISA IRQs are used. Note that + * if the BIOS doesn't set a Link Device active, ACPI needs to program it + * even if acpi_irq_nobalance is set. + * + * A tables of penalties avoids directing PCI interrupts to well known + * ISA IRQs. Boot params are available to over-ride the default table: * - * Never use: 0, 1, 2 (timer, keyboard, and cascade) - * Avoid using: 13, 14, and 15 (FP error and IDE) - * Penalize: 3, 4, 6, 7, 12 (known ISA uses) + * List interrupts that are free for PCI use. + * acpi_irq_pci=n[,m] * - * Thus we're left with IRQs 5, 9, 10, 11, and everything above 15 (IO[S]APIC) - * as 'best bets' for PCI use. + * List interrupts that should not be used for PCI: + * acpi_irq_isa=n[,m] + * + * Note that PCI IRQ routers have a list of possible IRQs, + * which may not include the IRQs this table says are available. + * + * Since this heuristic can't tell the difference between a link + * that no device will attach to, vs. a link which may be shared + * by multiple active devices -- it is not optimal. + * + * If interrupt performance is that important, get an IO-APIC system + * with a pin dedicated to each device. Or for that matter, an MSI + * enabled system. */ +#define ACPI_MAX_IRQS 256 +#define ACPI_MAX_ISA_IRQ 16 + +#define PIRQ_PENALTY_PCI_AVAILABLE (0) +#define PIRQ_PENALTY_PCI_POSSIBLE (16*16) +#define PIRQ_PENALTY_PCI_USING (16*16*16) +#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) +#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) +#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) + static int acpi_irq_penalty[ACPI_MAX_IRQS] = { - 1000000, 1000000, 1000000, 10000, - 10000, 0, 10000, 10000, - 10000, 0, 0, 0, - 10000, 100000, 100000, 100000, + PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ + PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ + PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ + PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ + PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ + PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ + PIRQ_PENALTY_ISA_TYPICAL, /* IRQ12 mouse */ + PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ + PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ + PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ + /* >IRQ15 */ }; - int acpi_pci_link_check (void) { @@ -473,20 +513,30 @@ continue; } - if (link->irq.active) - acpi_irq_penalty[link->irq.active] += 100; - else if (link->irq.possible_count) { - int penalty = 100 / link->irq.possible_count; - for (i=0; iirq.possible_count; i++) { + /* + * reflect the possible and active irqs in the penalty table -- + * useful for breaking ties. + */ + if (link->irq.possible_count) { + int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count; + + for (i = 0; i < link->irq.possible_count; i++) { if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) acpi_irq_penalty[link->irq.possible[i]] += penalty; } + + } else if (link->irq.active) { + acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE; } } + /* Add a penalty for the SCI */ + acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING; return_VALUE(0); } +static int acpi_irq_balance; /* 0: static, 1: balance */ + static int acpi_pci_link_allocate(struct acpi_pci_link* link) { int irq; int i; @@ -500,12 +550,14 @@ irq = link->irq.active; } else { irq = link->irq.possible[0]; + } + if (acpi_irq_balance || !link->irq.active) { /* * Select the best IRQ. This is done in reverse to promote * the use of IRQs 9, 10, 11, and >15. */ - for (i=(link->irq.possible_count-1); i>0; i--) { + for (i = (link->irq.possible_count - 1); i >= 0; i--) { if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) irq = link->irq.possible[i]; } @@ -518,13 +570,14 @@ acpi_device_bid(link->device)); return_VALUE(-ENODEV); } else { - acpi_irq_penalty[link->irq.active] += 100; + acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; printk(PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); } link->irq.setonboot = 1; + return_VALUE(0); } @@ -607,9 +660,12 @@ if (result) goto end; + /* query and set link->irq.active */ acpi_pci_link_get_current(link); - printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), acpi_device_bid(device)); +//#ifdef CONFIG_ACPI_DEBUG + printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), + acpi_device_bid(device)); for (i = 0; i < link->irq.possible_count; i++) { if (link->irq.active == link->irq.possible[i]) { printk(" *%d", link->irq.possible[i]); @@ -619,6 +675,7 @@ printk(" %d", link->irq.possible[i]); } printk(")\n"); +//#endif /* CONFIG_ACPI_DEBUG */ /* TBD: Acquire/release lock */ list_add_tail(&link->node, &acpi_link.entries); @@ -654,6 +711,77 @@ return_VALUE(0); } +/* + * modify acpi_irq_penalty[] from cmdline + */ +static int __init acpi_irq_penalty_update(char *str, int used) +{ + int i; + + for (i = 0; i < 16; i++) { + int retval; + int irq; + + retval = get_option(&str,&irq); + + if (!retval) + break; /* no number found */ + + if (irq < 0) + continue; + + if (irq >= ACPI_MAX_IRQS) + continue; + + if (used) + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + else + acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; + + if (retval != 2) /* no next number */ + break; + } + return 1; +} + +/* + * Over-ride default table to reserve additional IRQs for use by ISA + * e.g. acpi_irq_isa=5 + * Useful for telling ACPI how not to interfere with your ISA sound card. + */ +static int __init acpi_irq_isa(char *str) +{ + return(acpi_irq_penalty_update(str, 1)); +} +__setup("acpi_irq_isa=", acpi_irq_isa); + +/* + * Over-ride default table to free additional IRQs for use by PCI + * e.g. acpi_irq_pci=7,15 + * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing. + */ +static int __init acpi_irq_pci(char *str) +{ + return(acpi_irq_penalty_update(str, 0)); +} +__setup("acpi_irq_pci=", acpi_irq_pci); + +static int __init acpi_irq_nobalance_set(char *str) +{ +printk("ACPI STATIC SET\n"); + acpi_irq_balance = 0; + return(1); +} +__setup("acpi_irq_nobalance", acpi_irq_nobalance_set); + +int __init acpi_irq_balance_set(char *str) +{ +printk("ACPI BALANCE SET\n"); + acpi_irq_balance = 1; + return(1); +} +__setup("acpi_irq_balance", acpi_irq_balance_set); + static int __init acpi_pci_link_init (void) { diff -urN linux-2.6.2-rc2/drivers/acpi/pci_root.c linux-2.6.2-rc3/drivers/acpi/pci_root.c --- linux-2.6.2-rc2/drivers/acpi/pci_root.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/pci_root.c 2004-01-30 18:49:20.000000000 -0800 @@ -62,8 +62,6 @@ acpi_handle handle; struct acpi_pci_id id; struct pci_bus *bus; - u64 mem_tra; - u64 io_tra; }; static LIST_HEAD(acpi_pci_roots); @@ -115,97 +113,6 @@ } } -void -acpi_pci_get_translations ( - struct acpi_pci_id *id, - u64 *mem_tra, - u64 *io_tra) -{ - struct list_head *node = NULL; - struct acpi_pci_root *entry; - - /* TBD: Locking */ - list_for_each(node, &acpi_pci_roots) { - entry = list_entry(node, struct acpi_pci_root, node); - if ((id->segment == entry->id.segment) - && (id->bus == entry->id.bus)) { - *mem_tra = entry->mem_tra; - *io_tra = entry->io_tra; - return; - } - } - - *mem_tra = 0; - *io_tra = 0; -} - - -static u64 -acpi_pci_root_bus_tra ( - struct acpi_resource *resource, - int type) -{ - struct acpi_resource_address16 *address16; - struct acpi_resource_address32 *address32; - struct acpi_resource_address64 *address64; - - while (1) { - switch (resource->id) { - case ACPI_RSTYPE_END_TAG: - return 0; - - case ACPI_RSTYPE_ADDRESS16: - address16 = (struct acpi_resource_address16 *) &resource->data; - if (type == address16->resource_type) { - return address16->address_translation_offset; - } - break; - - case ACPI_RSTYPE_ADDRESS32: - address32 = (struct acpi_resource_address32 *) &resource->data; - if (type == address32->resource_type) { - return address32->address_translation_offset; - } - break; - - case ACPI_RSTYPE_ADDRESS64: - address64 = (struct acpi_resource_address64 *) &resource->data; - if (type == address64->resource_type) { - return address64->address_translation_offset; - } - break; - } - resource = ACPI_PTR_ADD (struct acpi_resource, - resource, resource->length); - } - - return 0; -} - - -static int -acpi_pci_evaluate_crs ( - struct acpi_pci_root *root) -{ - acpi_status status; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - - ACPI_FUNCTION_TRACE("acpi_pci_evaluate_crs"); - - status = acpi_get_current_resources (root->handle, &buffer); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - root->io_tra = acpi_pci_root_bus_tra ((struct acpi_resource *) - buffer.pointer, ACPI_IO_RANGE); - root->mem_tra = acpi_pci_root_bus_tra ((struct acpi_resource *) - buffer.pointer, ACPI_MEMORY_RANGE); - - acpi_os_free(buffer.pointer); - return_VALUE(0); -} - - static int acpi_pci_root_add ( struct acpi_device *device) @@ -288,10 +195,8 @@ root->id.function = device->pnp.bus_address & 0xFFFF; /* - * Evaluate _CRS to get root bridge resources * TBD: Need PCI interface for enumeration/configuration of roots. */ - acpi_pci_evaluate_crs(root); /* TBD: Locking */ list_add_tail(&root->node, &acpi_pci_roots); diff -urN linux-2.6.2-rc2/drivers/acpi/power.c linux-2.6.2-rc3/drivers/acpi/power.c --- linux-2.6.2-rc2/drivers/acpi/power.c 2004-01-08 22:59:42.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/power.c 2004-01-30 18:49:20.000000000 -0800 @@ -387,7 +387,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_power_dir = NULL; +struct proc_dir_entry *acpi_power_dir; static int acpi_power_seq_show(struct seq_file *seq, void *offset) { diff -urN linux-2.6.2-rc2/drivers/acpi/processor.c linux-2.6.2-rc3/drivers/acpi/processor.c --- linux-2.6.2-rc2/drivers/acpi/processor.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/processor.c 2004-01-30 18:49:20.000000000 -0800 @@ -138,7 +138,7 @@ static struct acpi_processor *processors[NR_CPUS]; static struct acpi_processor_errata errata; -static void (*pm_idle_save)(void) = NULL; +static void (*pm_idle_save)(void); /* -------------------------------------------------------------------------- diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsaddr.c linux-2.6.2-rc3/drivers/acpi/resources/rsaddr.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsaddr.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsaddr.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rscalc.c linux-2.6.2-rc3/drivers/acpi/resources/rscalc.c --- linux-2.6.2-rc2/drivers/acpi/resources/rscalc.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rscalc.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -696,7 +696,7 @@ default: /* * If we get here, everything is out of sync, - * so exit with an error + * exit with an error */ return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } @@ -704,7 +704,7 @@ /* * Update the return value and counter */ - buffer_size += ACPI_ALIGN_RESOURCE_SIZE(structure_size); + buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size); bytes_parsed += bytes_consumed; /* diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rscreate.c linux-2.6.2-rc3/drivers/acpi/resources/rscreate.c --- linux-2.6.2-rc2/drivers/acpi/resources/rscreate.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rscreate.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -331,7 +331,7 @@ /* Now align the current length */ - user_prt->length = ACPI_ROUND_UP_to_64_bITS (user_prt->length); + user_prt->length = (u32) ACPI_ROUND_UP_to_64_bITS (user_prt->length); /* * 4) Fourth subobject: Dereference the PRT.source_index diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsdump.c linux-2.6.2-rc3/drivers/acpi/resources/rsdump.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsdump.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsdump.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -899,24 +899,19 @@ "" : "not "); acpi_os_printf (" Granularity: %8.8X%8.8X\n", - ACPI_HIDWORD (address64_data->granularity), - ACPI_LODWORD (address64_data->granularity)); + ACPI_FORMAT_UINT64 (address64_data->granularity)); acpi_os_printf (" Address range min: %8.8X%8.8X\n", - ACPI_HIDWORD (address64_data->min_address_range), - ACPI_HIDWORD (address64_data->min_address_range)); + ACPI_FORMAT_UINT64 (address64_data->min_address_range)); acpi_os_printf (" Address range max: %8.8X%8.8X\n", - ACPI_HIDWORD (address64_data->max_address_range), - ACPI_HIDWORD (address64_data->max_address_range)); + ACPI_FORMAT_UINT64 (address64_data->max_address_range)); acpi_os_printf (" Address translation offset: %8.8X%8.8X\n", - ACPI_HIDWORD (address64_data->address_translation_offset), - ACPI_HIDWORD (address64_data->address_translation_offset)); + ACPI_FORMAT_UINT64 (address64_data->address_translation_offset)); acpi_os_printf (" Address Length: %8.8X%8.8X\n", - ACPI_HIDWORD (address64_data->address_length), - ACPI_HIDWORD (address64_data->address_length)); + ACPI_FORMAT_UINT64 (address64_data->address_length)); if(0xFF != address64_data->resource_source.index) { acpi_os_printf (" Resource Source Index: %X\n", @@ -1126,8 +1121,7 @@ acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++); acpi_os_printf (" Address: %8.8X%8.8X\n", - ACPI_HIDWORD (prt_element->address), - ACPI_LODWORD (prt_element->address)); + ACPI_FORMAT_UINT64 (prt_element->address)); acpi_os_printf (" Pin: %X\n", prt_element->pin); diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsio.c linux-2.6.2-rc3/drivers/acpi/resources/rsio.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsio.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsio.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsirq.c linux-2.6.2-rc3/drivers/acpi/resources/rsirq.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsirq.c 2004-01-08 23:00:12.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsirq.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,26 +132,28 @@ temp8 = *buffer; /* - * Check for HE, LL or HL + * Check for HE, LL interrupts */ - if (temp8 & 0x01) { + switch (temp8 & 0x09) { + case 0x01: /* HE */ output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE; output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH; - } - else { - if (temp8 & 0x8) { - output_struct->data.irq.edge_level = ACPI_LEVEL_SENSITIVE; - output_struct->data.irq.active_high_low = ACPI_ACTIVE_LOW; - } - else { - /* - * Only _LL and _HE polarity/trigger interrupts - * are allowed (ACPI spec v1.0b ection 6.4.2.1), - * so an error will occur if we reach this point - */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid interrupt polarity/trigger in resource list\n")); - return_ACPI_STATUS (AE_BAD_DATA); - } + break; + + case 0x08: /* LL */ + output_struct->data.irq.edge_level = ACPI_LEVEL_SENSITIVE; + output_struct->data.irq.active_high_low = ACPI_ACTIVE_LOW; + break; + + default: + /* + * Only _LL and _HE polarity/trigger interrupts + * are allowed (ACPI spec, section "IRQ Format") + * so 0x00 and 0x09 are illegal. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Invalid interrupt polarity/trigger in resource list, %X\n", temp8)); + return_ACPI_STATUS (AE_BAD_DATA); } /* @@ -419,7 +421,7 @@ * Point the String pointer to the end of this structure. */ output_struct->data.extended_irq.resource_source.string_ptr = - (char *)(output_struct + struct_size); + (char *)((char *) output_struct + struct_size); temp_ptr = (u8 *) output_struct->data.extended_irq.resource_source.string_ptr; diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rslist.c linux-2.6.2-rc3/drivers/acpi/resources/rslist.c --- linux-2.6.2-rc2/drivers/acpi/resources/rslist.c 2004-01-08 23:00:13.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rslist.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -312,8 +312,8 @@ * Set the Buffer to the next structure */ resource = ACPI_CAST_PTR (struct acpi_resource, buffer); - resource->length = ACPI_ALIGN_RESOURCE_SIZE(resource->length); - buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size); + resource->length = (u32) ACPI_ALIGN_RESOURCE_SIZE (resource->length); + buffer += ACPI_ALIGN_RESOURCE_SIZE (structure_size); } /* end while */ diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsmemory.c linux-2.6.2-rc3/drivers/acpi/resources/rsmemory.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsmemory.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsmemory.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsmisc.c linux-2.6.2-rc3/drivers/acpi/resources/rsmisc.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsmisc.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsmisc.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsutils.c linux-2.6.2-rc3/drivers/acpi/resources/rsutils.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsutils.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsutils.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/resources/rsxface.c linux-2.6.2-rc3/drivers/acpi/resources/rsxface.c --- linux-2.6.2-rc2/drivers/acpi/resources/rsxface.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/resources/rsxface.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/scan.c linux-2.6.2-rc3/drivers/acpi/scan.c --- linux-2.6.2-rc2/drivers/acpi/scan.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/scan.c 2004-01-30 18:49:20.000000000 -0800 @@ -336,6 +336,9 @@ ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); + if (acpi_disabled) + return_VALUE(-ENODEV); + if (driver) { spin_lock(&acpi_device_lock); list_add_tail(&driver->node, &acpi_bus_drivers); @@ -703,11 +706,11 @@ switch (type) { case ACPI_BUS_TYPE_DEVICE: result = acpi_bus_get_status(device); - if (!result) - break; - if (!device->status.present) + if (ACPI_FAILURE(result) || !device->status.present) { result = -ENOENT; - goto end; + goto end; + } + break; default: STRUCT_TO_INT(device->status) = 0x0F; break; diff -urN linux-2.6.2-rc2/drivers/acpi/sleep/proc.c linux-2.6.2-rc3/drivers/acpi/sleep/proc.c --- linux-2.6.2-rc2/drivers/acpi/sleep/proc.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/sleep/proc.c 2004-01-30 18:49:20.000000000 -0800 @@ -374,6 +374,9 @@ { struct proc_dir_entry *entry = NULL; + if (acpi_disabled) + return 0; + /* 'sleep' [R/W]*/ entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir); diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbconvrt.c linux-2.6.2-rc3/drivers/acpi/tables/tbconvrt.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbconvrt.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbconvrt.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -138,11 +138,11 @@ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { if (acpi_gbl_RSDP->revision < 2) { ACPI_STORE_ADDRESS (new_table->table_offset_entry[i], - ((struct rsdt_descriptor_rev1 *) table_info->pointer)->table_offset_entry[i]); + (ACPI_CAST_PTR (struct rsdt_descriptor_rev1, table_info->pointer))->table_offset_entry[i]); } else { new_table->table_offset_entry[i] = - ((XSDT_DESCRIPTOR *) table_info->pointer)->table_offset_entry[i]; + (ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info->pointer))->table_offset_entry[i]; } } @@ -152,7 +152,7 @@ /* Point the table descriptor to the new table */ - table_info->pointer = (struct acpi_table_header *) new_table; + table_info->pointer = ACPI_CAST_PTR (struct acpi_table_header, new_table); table_info->length = table_size; table_info->allocation = ACPI_MEM_ALLOCATED; @@ -469,7 +469,7 @@ /* Install the new table */ - table_desc->pointer = (struct acpi_table_header *) acpi_gbl_FADT; + table_desc->pointer = ACPI_CAST_PTR (struct acpi_table_header, acpi_gbl_FADT); table_desc->allocation = ACPI_MEM_ALLOCATED; table_desc->length = sizeof (struct fadt_descriptor_rev2); diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbget.c linux-2.6.2-rc3/drivers/acpi/tables/tbget.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbget.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbget.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -148,8 +148,7 @@ (void *) &header); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not map memory at %8.8X%8.8X for length %X\n", - ACPI_HIDWORD (address->pointer.physical), - ACPI_LODWORD (address->pointer.physical), + ACPI_FORMAT_UINT64 (address->pointer.physical), sizeof (struct acpi_table_header))); return_ACPI_STATUS (status); } @@ -365,8 +364,7 @@ if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, - ACPI_HIDWORD (address->pointer.physical), - ACPI_LODWORD (address->pointer.physical), header->length)); + ACPI_FORMAT_UINT64 (address->pointer.physical), header->length)); return (status); } @@ -408,8 +406,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n", full_table->signature, - ACPI_HIDWORD (address->pointer.physical), - ACPI_LODWORD (address->pointer.physical), full_table)); + ACPI_FORMAT_UINT64 (address->pointer.physical), full_table)); return_ACPI_STATUS (status); } @@ -458,6 +455,7 @@ if (instance == 1) { /* Get the first */ + *table_ptr_loc = NULL; if (acpi_gbl_table_lists[table_type].next) { *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer; } diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbgetall.c linux-2.6.2-rc3/drivers/acpi/tables/tbgetall.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbgetall.c 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbgetall.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -240,8 +240,7 @@ if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) { ACPI_REPORT_WARNING (("%s, while getting table at %8.8X%8.8X\n", acpi_format_exception (status), - ACPI_HIDWORD (address.pointer.value), - ACPI_LODWORD (address.pointer.value))); + ACPI_FORMAT_UINT64 (address.pointer.value))); } } diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbinstal.c linux-2.6.2-rc3/drivers/acpi/tables/tbinstal.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbinstal.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbinstal.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbrsdt.c linux-2.6.2-rc3/drivers/acpi/tables/tbrsdt.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbrsdt.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbrsdt.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -233,6 +233,15 @@ acpi_gbl_RSDP->rsdt_physical_address, (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address)); + if (acpi_gbl_RSDP->revision < 2) { + ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n")) + } + else { + ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n")) + } + + ACPI_DUMP_BUFFER ((char *) table_ptr, 48); + return (AE_BAD_SIGNATURE); } @@ -278,8 +287,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, - ACPI_HIDWORD (address.pointer.value), - ACPI_LODWORD (address.pointer.value))); + ACPI_FORMAT_UINT64 (address.pointer.value))); /* Check the RSDT or XSDT signature */ @@ -306,7 +314,7 @@ return_ACPI_STATUS (status); } - acpi_gbl_XSDT = (XSDT_DESCRIPTOR *) table_info.pointer; + acpi_gbl_XSDT = ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info.pointer); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); return_ACPI_STATUS (status); diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbutils.c linux-2.6.2-rc3/drivers/acpi/tables/tbutils.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbutils.c 2004-01-08 22:59:55.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbutils.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbxface.c linux-2.6.2-rc3/drivers/acpi/tables/tbxface.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbxface.c 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbxface.c 2004-01-30 18:49:20.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -251,7 +251,7 @@ /* Find all tables of the requested type */ table_desc = acpi_gbl_table_lists[table_type].next; - while (table_desc); { + while (table_desc) { /* * Delete all namespace entries owned by this table. Note that these * entries can appear anywhere in the namespace by virtue of the AML diff -urN linux-2.6.2-rc2/drivers/acpi/tables/tbxfroot.c linux-2.6.2-rc3/drivers/acpi/tables/tbxfroot.c --- linux-2.6.2-rc2/drivers/acpi/tables/tbxfroot.c 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables/tbxfroot.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -211,8 +211,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, - ACPI_HIDWORD (address.pointer.value), - ACPI_LODWORD (address.pointer.value))); + ACPI_FORMAT_UINT64 (address.pointer.value))); /* Insert processor_mode flags */ @@ -242,11 +241,11 @@ /* Get the next table pointer, handle RSDT vs. XSDT */ if (acpi_gbl_RSDP->revision < 2) { - address.pointer.value = ((RSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i]; + address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i]; } else { address.pointer.value = - ((XSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i]; + (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i]; } /* Get the table header */ diff -urN linux-2.6.2-rc2/drivers/acpi/tables.c linux-2.6.2-rc3/drivers/acpi/tables.c --- linux-2.6.2-rc2/drivers/acpi/tables.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/tables.c 2004-01-30 18:49:20.000000000 -0800 @@ -60,6 +60,9 @@ [ACPI_HPET] = "HPET", }; +static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; +static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; + /* System Description Table (RSDT/XSDT) */ struct acpi_table_sdt { unsigned long pa; @@ -136,8 +139,14 @@ { struct acpi_table_int_src_ovr *p = (struct acpi_table_int_src_ovr*) header; - printk(KERN_INFO PREFIX "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n", - p->bus, p->bus_irq, p->global_irq, p->flags.polarity, p->flags.trigger); + printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", + p->bus, p->bus_irq, p->global_irq, + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger]); + if(p->flags.reserved) + printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n", + p->flags.reserved); + } break; @@ -145,8 +154,9 @@ { struct acpi_table_nmi_src *p = (struct acpi_table_nmi_src*) header; - printk(KERN_INFO PREFIX "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n", - p->flags.polarity, p->flags.trigger, p->global_irq); + printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n", + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger], p->global_irq); } break; @@ -154,8 +164,10 @@ { struct acpi_table_lapic_nmi *p = (struct acpi_table_lapic_nmi*) header; - printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n", - p->acpi_id, p->flags.polarity, p->flags.trigger, p->lint); + printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", + p->acpi_id, + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger], p->lint); } break; @@ -190,8 +202,10 @@ { struct acpi_table_plat_int_src *p = (struct acpi_table_plat_int_src*) header; - printk(KERN_INFO PREFIX "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", - p->flags.polarity, p->flags.trigger, p->type, p->id, p->eid, p->iosapic_vector, p->global_irq); + printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger], + p->type, p->id, p->eid, p->iosapic_vector, p->global_irq); } break; @@ -262,10 +276,17 @@ /* Map the DSDT header via the pointer in the FADT */ if (id == ACPI_DSDT) { - struct acpi_table_fadt *fadt = (struct acpi_table_fadt *) *header; + struct fadt_descriptor_rev2 *fadt = (struct fadt_descriptor_rev2 *) *header; + + if (fadt->revision == 3 && fadt->Xdsdt) { + *header = (void *) __acpi_map_table(fadt->Xdsdt, + sizeof(struct acpi_table_header)); + } else if (fadt->V1_dsdt) { + *header = (void *) __acpi_map_table(fadt->V1_dsdt, + sizeof(struct acpi_table_header)); + } else + *header = 0; - *header = (void *) __acpi_map_table(fadt->dsdt_addr, - sizeof(struct acpi_table_header)); if (!*header) { printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); return -ENODEV; diff -urN linux-2.6.2-rc2/drivers/acpi/thermal.c linux-2.6.2-rc3/drivers/acpi/thermal.c --- linux-2.6.2-rc2/drivers/acpi/thermal.c 2004-01-08 22:59:57.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/thermal.c 2004-01-30 18:49:20.000000000 -0800 @@ -74,7 +74,7 @@ MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); MODULE_LICENSE("GPL"); -static int tzp = 0; +static int tzp; MODULE_PARM(tzp, "i"); MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); @@ -467,6 +467,7 @@ if (result) return_VALUE(result); + printk(KERN_EMERG "Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz->temperature)); acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF); @@ -765,7 +766,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_thermal_dir = NULL; +struct proc_dir_entry *acpi_thermal_dir; static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) { diff -urN linux-2.6.2-rc2/drivers/acpi/toshiba_acpi.c linux-2.6.2-rc3/drivers/acpi/toshiba_acpi.c --- linux-2.6.2-rc2/drivers/acpi/toshiba_acpi.c 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/toshiba_acpi.c 2004-01-30 18:49:20.000000000 -0800 @@ -215,7 +215,7 @@ return status; } -static struct proc_dir_entry* toshiba_proc_dir = NULL; +static struct proc_dir_entry* toshiba_proc_dir; static int force_fan; static int last_key_event; static int key_event_valid; diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utalloc.c linux-2.6.2-rc3/drivers/acpi/utilities/utalloc.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utalloc.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utalloc.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -902,71 +902,30 @@ descriptor = ACPI_CAST_PTR (union acpi_descriptor, &element->user_space); if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) { - acpi_os_printf ("%p Len %04X %9.9s-%d ", + acpi_os_printf ("%p Len %04X %9.9s-%d [%s] ", descriptor, element->size, element->module, - element->line); + element->line, acpi_ut_get_descriptor_name (descriptor)); - /* Most of the elements will be internal objects. */ + /* Most of the elements will be Operand objects. */ switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) { case ACPI_DESC_TYPE_OPERAND: - acpi_os_printf ("obj_type %12.12s R%hd", + acpi_os_printf ("%12.12s R%hd", acpi_ut_get_type_name (descriptor->object.common.type), descriptor->object.common.reference_count); break; case ACPI_DESC_TYPE_PARSER: - acpi_os_printf ("parse_obj aml_opcode %04hX", + acpi_os_printf ("aml_opcode %04hX", descriptor->op.asl.aml_opcode); break; case ACPI_DESC_TYPE_NAMED: - acpi_os_printf ("Node %4.4s", - descriptor->node.name.ascii); - break; - - case ACPI_DESC_TYPE_STATE: - acpi_os_printf ("Untyped state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_UPDATE: - acpi_os_printf ("UPDATE state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_PACKAGE: - acpi_os_printf ("PACKAGE state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_CONTROL: - acpi_os_printf ("CONTROL state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_RPSCOPE: - acpi_os_printf ("ROOT-PARSE-SCOPE state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_PSCOPE: - acpi_os_printf ("PARSE-SCOPE state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_WSCOPE: - acpi_os_printf ("WALK-SCOPE state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_RESULT: - acpi_os_printf ("RESULT state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_NOTIFY: - acpi_os_printf ("NOTIFY state_obj"); - break; - - case ACPI_DESC_TYPE_STATE_THREAD: - acpi_os_printf ("THREAD state_obj"); + acpi_os_printf ("%4.4s", + acpi_ut_get_node_name (&descriptor->node)); break; default: - /* All types should appear above */ break; } diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utcopy.c linux-2.6.2-rc3/drivers/acpi/utilities/utcopy.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utcopy.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utcopy.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utdebug.c linux-2.6.2-rc3/drivers/acpi/utilities/utdebug.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utdebug.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utdebug.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -447,7 +447,7 @@ acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, - ACPI_HIDWORD (value), ACPI_LODWORD (value)); + ACPI_FORMAT_UINT64 (value)); acpi_gbl_nesting_level--; } diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utdelete.c linux-2.6.2-rc3/drivers/acpi/utilities/utdelete.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utdelete.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utdelete.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -140,7 +140,7 @@ /* Walk the handler list for this device */ - handler_desc = object->device.address_space; + handler_desc = object->device.handler; while (handler_desc) { next_desc = handler_desc->address_space.next; acpi_ut_remove_reference (handler_desc); @@ -193,7 +193,7 @@ * default handlers -- and therefore, we created the context object * locally, it was not created by an external caller. */ - handler_desc = object->region.address_space; + handler_desc = object->region.handler; if (handler_desc) { if (handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { obj_pointer = second_desc->extra.region_context; diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/uteval.c linux-2.6.2-rc3/drivers/acpi/utilities/uteval.c --- linux-2.6.2-rc2/drivers/acpi/utilities/uteval.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/uteval.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -91,7 +91,7 @@ if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n", - prefix_node->name.ascii, path)); + acpi_ut_get_node_name (prefix_node), path)); } else { ACPI_REPORT_METHOD_ERROR ("Method execution failed", @@ -544,7 +544,7 @@ if (AE_NOT_FOUND == status) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_STA on %4.4s was not found, assuming device is present\n", - device_node->name.ascii)); + acpi_ut_get_node_name (device_node))); *flags = 0x0F; status = AE_OK; diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utglobal.c linux-2.6.2-rc3/drivers/acpi/utilities/utglobal.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utglobal.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utglobal.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -358,7 +358,7 @@ /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, ACPI_BITREG_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, ACPI_BITREG_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_ENABLE}, /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, - /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, 0, 0}, + /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE}, }; /***************************************************************************** @@ -534,6 +534,99 @@ } +/***************************************************************************** + * + * FUNCTION: acpi_ut_get_node_name + * + * PARAMETERS: Object - A namespace node + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Validate the node and return the node's ACPI name. + * + ****************************************************************************/ + +char * +acpi_ut_get_node_name ( + void *object) +{ + struct acpi_namespace_node *node; + + + if (!object) + { + return ("NULL NODE"); + } + + node = (struct acpi_namespace_node *) object; + + if (node->descriptor != ACPI_DESC_TYPE_NAMED) + { + return ("****"); + } + + if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii)) + { + return ("----"); + } + + return (node->name.ascii); +} + + +/***************************************************************************** + * + * FUNCTION: acpi_ut_get_descriptor_name + * + * PARAMETERS: Object - An ACPI object + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Validate object and return the descriptor type + * + ****************************************************************************/ + +static const char *acpi_gbl_desc_type_names[] = /* printable names of descriptor types */ +{ + /* 00 */ "Invalid", + /* 01 */ "Cached", + /* 02 */ "State-Generic", + /* 03 */ "State-Update", + /* 04 */ "State-Package", + /* 05 */ "State-Control", + /* 06 */ "State-root_parse_scope", + /* 07 */ "State-parse_scope", + /* 08 */ "State-walk_scope", + /* 09 */ "State-Result", + /* 10 */ "State-Notify", + /* 11 */ "State-Thread", + /* 12 */ "Walk", + /* 13 */ "Parser", + /* 14 */ "Operand", + /* 15 */ "Node" +}; + + +char * +acpi_ut_get_descriptor_name ( + void *object) +{ + + if (!object) + { + return ("NULL OBJECT"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (object) > ACPI_DESC_TYPE_MAX) + { + return ((char *) acpi_gbl_bad_type); + } + + return ((char *) acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE (object)]); + +} + + #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* * Strings and procedures used for debug only diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utinit.c linux-2.6.2-rc3/drivers/acpi/utilities/utinit.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utinit.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utinit.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utmath.c linux-2.6.2-rc3/drivers/acpi/utilities/utmath.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utmath.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utmath.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utmisc.c linux-2.6.2-rc3/drivers/acpi/utilities/utmisc.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utmisc.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utmisc.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -304,16 +304,20 @@ u32 name) { char *name_ptr = (char *) &name; - u32 i; + char character; + acpi_native_uint i; ACPI_FUNCTION_ENTRY (); for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (!((name_ptr[i] == '_') || - (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') || - (name_ptr[i] >= '0' && name_ptr[i] <= '9'))) { + character = *name_ptr; + name_ptr++; + + if (!((character == '_') || + (character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9'))) { return (FALSE); } } diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utobject.c linux-2.6.2-rc3/drivers/acpi/utilities/utobject.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utobject.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utobject.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -223,29 +223,10 @@ return (TRUE); - case ACPI_DESC_TYPE_NAMED: - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "**** Obj %p is a named obj, not ACPI obj\n", object)); - break; - - case ACPI_DESC_TYPE_PARSER: - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "**** Obj %p is a parser obj, not ACPI obj\n", object)); - break; - - case ACPI_DESC_TYPE_CACHED: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "**** Obj %p has already been released to internal cache\n", object)); - break; - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "**** Obj %p has unknown descriptor type %X\n", object, - ACPI_GET_DESCRIPTOR_TYPE (object))); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "%p is not not an ACPI operand obj [%s]\n", + object, acpi_ut_get_descriptor_name (object))); break; } @@ -322,7 +303,8 @@ if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Obj %p is not an ACPI object\n", object)); + "%p is not an ACPI Operand object [%s]\n", object, + acpi_ut_get_descriptor_name (object))); return_VOID; } diff -urN linux-2.6.2-rc2/drivers/acpi/utilities/utxface.c linux-2.6.2-rc3/drivers/acpi/utilities/utxface.c --- linux-2.6.2-rc2/drivers/acpi/utilities/utxface.c 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/acpi/utilities/utxface.c 2004-01-30 18:49:20.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/drivers/cpufreq/cpufreq.c linux-2.6.2-rc3/drivers/cpufreq/cpufreq.c --- linux-2.6.2-rc2/drivers/cpufreq/cpufreq.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/cpufreq/cpufreq.c 2004-01-30 18:49:20.000000000 -0800 @@ -868,7 +868,7 @@ down(&data->lock); memcpy(&policy, - &data, + data, sizeof(struct cpufreq_policy)); policy.min = data->user_policy.min; policy.max = data->user_policy.max; diff -urN linux-2.6.2-rc2/drivers/i2c/busses/i2c-parport.h linux-2.6.2-rc3/drivers/i2c/busses/i2c-parport.h --- linux-2.6.2-rc2/drivers/i2c/busses/i2c-parport.h 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/i2c/busses/i2c-parport.h 2004-01-30 18:49:20.000000000 -0800 @@ -67,12 +67,13 @@ .getsda = { 0x40, STAT, 1 }, .getscl = { 0x08, STAT, 1 }, }, - /* type 4: ADM 1032 evaluation board */ + /* type 4: ADM1025 and ADM1032 evaluation boards */ { .setsda = { 0x02, DATA, 1 }, .setscl = { 0x01, DATA, 1 }, .getsda = { 0x10, STAT, 1 }, - .init = { 0xf0, DATA, 0 }, + .init = { 0xf0, DATA, 0 }, /* ADM1025 doesn't need this, + but it doesn't hurt */ }, }; @@ -84,4 +85,4 @@ " 1 = home brew teletext adapter\n" " 2 = Velleman K8000 adapter\n" " 3 = ELV adapter\n" - " 4 = ADM 1032 evalulation board\n"); + " 4 = ADM1025 and ADM1032 evaluation boards\n"); diff -urN linux-2.6.2-rc2/drivers/i2c/busses/i2c-philips-par.c linux-2.6.2-rc3/drivers/i2c/busses/i2c-philips-par.c --- linux-2.6.2-rc2/drivers/i2c/busses/i2c-philips-par.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/i2c/busses/i2c-philips-par.c 2004-01-30 18:49:20.000000000 -0800 @@ -184,8 +184,8 @@ return; } /* reset hardware to sane state */ - bit_lp_setsda(port, 1); - bit_lp_setscl(port, 1); + adapter->bit_lp_data.setsda(port, 1); + adapter->bit_lp_data.setscl(port, 1); parport_release(adapter->pdev); if (i2c_bit_add_bus(&adapter->adapter) < 0) { diff -urN linux-2.6.2-rc2/drivers/i2c/busses/i2c-piix4.c linux-2.6.2-rc3/drivers/i2c/busses/i2c-piix4.c --- linux-2.6.2-rc2/drivers/i2c/busses/i2c-piix4.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/i2c/busses/i2c-piix4.c 2004-01-30 18:49:20.000000000 -0800 @@ -68,6 +68,9 @@ #define SMBSLVEVT (0xA + piix4_smba) #define SMBSLVDAT (0xC + piix4_smba) +/* count for request_region */ +#define SMBIOSIZE 8 + /* PCI Address Constants */ #define SMBBA 0x090 #define SMBHSTCFG 0x0D2 @@ -112,14 +115,13 @@ static int piix4_transaction(void); - static unsigned short piix4_smba = 0; static struct i2c_adapter piix4_adapter; /* * Get DMI information. */ -static int ibm_dmi_probe(void) +static int __devinit ibm_dmi_probe(void) { #ifdef CONFIG_X86 extern int is_unsafe_smbus; @@ -129,9 +131,9 @@ #endif } -static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id) +static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id) { - int error_return = 0; unsigned char temp; /* match up the function */ @@ -144,8 +146,7 @@ dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module " "may corrupt your serial eeprom! Refusing to load " "module!\n"); - error_return = -EPERM; - goto END; + return -EPERM; } /* Determine the address of the SMBus areas */ @@ -163,11 +164,10 @@ } } - if (!request_region(piix4_smba, 8, "piix4-smbus")) { + if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) { dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n", piix4_smba); - error_return = -ENODEV; - goto END; + return -ENODEV; } pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); @@ -214,8 +214,9 @@ } else { dev_err(&PIIX4_dev->dev, "Host SMBus controller not enabled!\n"); - error_return = -ENODEV; - goto END; + release_region(piix4_smba, SMBIOSIZE); + piix4_smba = 0; + return -ENODEV; } } @@ -231,8 +232,7 @@ dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp); dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba); -END: - return error_return; + return 0; } /* Another internally used function */ @@ -465,7 +465,8 @@ { 0, } }; -static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit piix4_probe(struct pci_dev *dev, + const struct pci_device_id *id) { int retval; @@ -479,17 +480,24 @@ snprintf(piix4_adapter.name, I2C_NAME_SIZE, "SMBus PIIX4 adapter at %04x", piix4_smba); - retval = i2c_add_adapter(&piix4_adapter); + if ((retval = i2c_add_adapter(&piix4_adapter))) { + dev_err(&dev->dev, "Couldn't register adapter!\n"); + release_region(piix4_smba, SMBIOSIZE); + piix4_smba = 0; + } return retval; } static void __devexit piix4_remove(struct pci_dev *dev) { - i2c_del_adapter(&piix4_adapter); + if (piix4_smba) { + i2c_del_adapter(&piix4_adapter); + release_region(piix4_smba, SMBIOSIZE); + piix4_smba = 0; + } } - static struct pci_driver piix4_driver = { .name = "piix4-smbus", .id_table = piix4_ids, @@ -502,15 +510,13 @@ return pci_module_init(&piix4_driver); } - static void __exit i2c_piix4_exit(void) { pci_unregister_driver(&piix4_driver); - release_region(piix4_smba, 8); } -MODULE_AUTHOR - ("Frodo Looijaard and Philip Edelbrock "); +MODULE_AUTHOR("Frodo Looijaard and " + "Philip Edelbrock "); MODULE_DESCRIPTION("PIIX4 SMBus driver"); MODULE_LICENSE("GPL"); diff -urN linux-2.6.2-rc2/drivers/i2c/chips/lm75.c linux-2.6.2-rc3/drivers/i2c/chips/lm75.c --- linux-2.6.2-rc2/drivers/i2c/chips/lm75.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/i2c/chips/lm75.c 2004-01-30 18:49:20.000000000 -0800 @@ -104,9 +104,9 @@ set(temp_max, LM75_REG_TEMP_OS); set(temp_hyst, LM75_REG_TEMP_HYST); -static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); -static DEVICE_ATTR(temp_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); -static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL); +static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); +static DEVICE_ATTR(temp_hyst1, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); +static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input, NULL); static int lm75_attach_adapter(struct i2c_adapter *adapter) { @@ -197,9 +197,9 @@ lm75_init_client(new_client); /* Register sysfs hooks */ - device_create_file(&new_client->dev, &dev_attr_temp_max); - device_create_file(&new_client->dev, &dev_attr_temp_hyst); - device_create_file(&new_client->dev, &dev_attr_temp_input); + device_create_file(&new_client->dev, &dev_attr_temp_max1); + device_create_file(&new_client->dev, &dev_attr_temp_hyst1); + device_create_file(&new_client->dev, &dev_attr_temp_input1); return 0; diff -urN linux-2.6.2-rc2/drivers/i2c/chips/lm78.c linux-2.6.2-rc3/drivers/i2c/chips/lm78.c --- linux-2.6.2-rc2/drivers/i2c/chips/lm78.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/i2c/chips/lm78.c 2004-01-30 18:49:20.000000000 -0800 @@ -369,10 +369,10 @@ return count; } -static DEVICE_ATTR(temp_input, S_IRUGO, show_temp, NULL) -static DEVICE_ATTR(temp_max, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp, NULL) +static DEVICE_ATTR(temp_max1, S_IRUGO | S_IWUSR, show_temp_over, set_temp_over) -static DEVICE_ATTR(temp_hyst, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(temp_hyst1, S_IRUGO | S_IWUSR, show_temp_hyst, set_temp_hyst) /* 3 Fans */ @@ -678,9 +678,9 @@ device_create_file(&new_client->dev, &dev_attr_in_input6); device_create_file(&new_client->dev, &dev_attr_in_min6); device_create_file(&new_client->dev, &dev_attr_in_max6); - device_create_file(&new_client->dev, &dev_attr_temp_input); - device_create_file(&new_client->dev, &dev_attr_temp_max); - device_create_file(&new_client->dev, &dev_attr_temp_hyst); + device_create_file(&new_client->dev, &dev_attr_temp_input1); + device_create_file(&new_client->dev, &dev_attr_temp_max1); + device_create_file(&new_client->dev, &dev_attr_temp_hyst1); device_create_file(&new_client->dev, &dev_attr_fan_input1); device_create_file(&new_client->dev, &dev_attr_fan_min1); device_create_file(&new_client->dev, &dev_attr_fan_div1); diff -urN linux-2.6.2-rc2/drivers/i2c/chips/lm85.c linux-2.6.2-rc3/drivers/i2c/chips/lm85.c --- linux-2.6.2-rc2/drivers/i2c/chips/lm85.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/i2c/chips/lm85.c 2004-01-30 18:49:20.000000000 -0800 @@ -48,9 +48,6 @@ /* Insmod parameters */ SENSORS_INSMOD_4(lm85b, lm85c, adm1027, adt7463); -/* Enable debug if true */ -static int lm85debug = 0; - /* The LM85 registers */ #define LM85_REG_IN(nr) (0x20 + (nr)) @@ -802,19 +799,15 @@ company = lm85_read_value(new_client, LM85_REG_COMPANY); verstep = lm85_read_value(new_client, LM85_REG_VERSTEP); - if (lm85debug) { - printk("lm85: Detecting device at %d,0x%02x with" + dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with" " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", i2c_adapter_id(new_client->adapter), new_client->addr, company, verstep); - } /* If auto-detecting, Determine the chip type. */ if (kind <= 0) { - if (lm85debug) { - printk("lm85: Autodetecting device at %d,0x%02x ...\n", + dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x ...\n", i2c_adapter_id(adapter), address ); - } if( company == LM85_COMPANY_NATIONAL && verstep == LM85_VERSTEP_LM85C ) { kind = lm85c ; @@ -823,8 +816,8 @@ kind = lm85b ; } else if( company == LM85_COMPANY_NATIONAL && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) { - printk("lm85: Unrecgonized version/stepping 0x%02x" - " Defaulting to LM85.\n", verstep ); + dev_err(&adapter->dev, "Unrecgonized version/stepping 0x%02x" + " Defaulting to LM85.\n", verstep); kind = any_chip ; } else if( company == LM85_COMPANY_ANALOG_DEV && verstep == LM85_VERSTEP_ADM1027 ) { @@ -834,21 +827,19 @@ kind = adt7463 ; } else if( company == LM85_COMPANY_ANALOG_DEV && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) { - printk("lm85: Unrecgonized version/stepping 0x%02x" - " Defaulting to ADM1027.\n", verstep ); + dev_err(&adapter->dev, "Unrecgonized version/stepping 0x%02x" + " Defaulting to ADM1027.\n", verstep); kind = adm1027 ; } else if( kind == 0 && (verstep & 0xf0) == 0x60) { - printk("lm85: Generic LM85 Version 6 detected\n"); + dev_err(&adapter->dev, "Generic LM85 Version 6 detected\n"); /* Leave kind as "any_chip" */ } else { - if (lm85debug) { - printk("lm85: Autodetection failed\n"); - } + dev_dbg(&adapter->dev, "Autodetection failed\n"); /* Not an LM85 ... */ if( kind == 0 ) { /* User used force=x,y */ - printk("lm85: Generic LM85 Version 6 not" - " found at %d,0x%02x. Try force_lm85c.\n", - i2c_adapter_id(adapter), address ); + dev_err(&adapter->dev, "Generic LM85 Version 6 not" + " found at %d,0x%02x. Try force_lm85c.\n", + i2c_adapter_id(adapter), address ); } err = 0 ; goto ERROR1; @@ -879,12 +870,10 @@ data->valid = 0; init_MUTEX(&data->update_lock); - if (lm85debug) { - printk("lm85: Assigning ID %d to %s at %d,0x%02x\n", + dev_dbg(&adapter->dev, "Assigning ID %d to %s at %d,0x%02x\n", new_client->id, new_client->name, i2c_adapter_id(new_client->adapter), new_client->addr); - } /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1021,31 +1010,24 @@ int value; struct lm85_data *data = i2c_get_clientdata(client); - if (lm85debug) { - printk("lm85(%d): Initializing device\n", client->id); - } + dev_dbg(&client->dev, "Initializing device\n"); /* Warn if part was not "READY" */ value = lm85_read_value(client, LM85_REG_CONFIG); - if (lm85debug) { - printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value ); - } + dev_dbg(&client->dev, "LM85_REG_CONFIG is: 0x%02x\n", value); if( value & 0x02 ) { - printk("lm85(%d): Client (%d,0x%02x) config is locked.\n", - client->id, + dev_err(&client->dev, "Client (%d,0x%02x) config is locked.\n", i2c_adapter_id(client->adapter), client->addr ); }; if( ! (value & 0x04) ) { - printk("lm85(%d): Client (%d,0x%02x) is not ready.\n", - client->id, + dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n", i2c_adapter_id(client->adapter), client->addr ); }; if( value & 0x10 && ( data->type == adm1027 || data->type == adt7463 ) ) { - printk("lm85(%d): Client (%d,0x%02x) VxI mode is set. " + dev_err(&client->dev, "Client (%d,0x%02x) VxI mode is set. " "Please report this to the lm85 maintainer.\n", - client->id, i2c_adapter_id(client->adapter), client->addr ); }; @@ -1061,11 +1043,8 @@ value = lm85_read_value(client, LM85_REG_CONFIG); /* Try to clear LOCK, Set START, save everything else */ value = (value & ~ 0x02) | 0x01 ; - if (lm85debug) { - printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value ); - } + dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); lm85_write_value(client, LM85_REG_CONFIG, value); - } void lm85_update_client(struct i2c_client *client) @@ -1078,10 +1057,8 @@ if ( !data->valid || (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) { /* Things that change quickly */ - - if (lm85debug) { - printk("lm85(%d): Reading sensor values\n", client->id); - } + dev_dbg(&client->dev, "Reading sensor values\n"); + /* Have to read extended bits first to "freeze" the * more significant bits that are read later. */ @@ -1125,10 +1102,8 @@ if ( !data->valid || (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) { /* Things that don't change often */ + dev_dbg(&client->dev, "Reading config values\n"); - if (lm85debug) { - printk("lm85(%d): Reading config values\n", client->id); - } for (i = 0; i <= 4; ++i) { data->in_min[i] = lm85_read_value(client, LM85_REG_IN_MIN(i)); @@ -1234,8 +1209,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Philip Pokorny , Margit Schubert-While "); MODULE_DESCRIPTION("LM85-B, LM85-C driver"); -MODULE_PARM(lm85debug, "i"); -MODULE_PARM_DESC(lm85debug, "Enable debugging statements"); module_init(sm_lm85_init); module_exit(sm_lm85_exit); diff -urN linux-2.6.2-rc2/drivers/media/common/saa7146_hlp.c linux-2.6.2-rc3/drivers/media/common/saa7146_hlp.c --- linux-2.6.2-rc2/drivers/media/common/saa7146_hlp.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/common/saa7146_hlp.c 2004-01-30 18:49:21.000000000 -0800 @@ -1,10 +1,6 @@ +#include #include -#define my_min(type,x,y) \ - ({ type __x = (x), __y = (y); __x < __y ? __x: __y; }) -#define my_max(type,x,y) \ - ({ type __x = (x), __y = (y); __x > __y ? __x: __y; }) - static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format) { /* clear out the necessary bits */ @@ -398,11 +394,11 @@ b = y[i]+h[i]; /* insert left/right coordinates */ - pixel_list[ 2*i ] = my_min(int, l, width); - pixel_list[(2*i)+1] = my_min(int, r, width); + pixel_list[ 2*i ] = min_t(int, l, width); + pixel_list[(2*i)+1] = min_t(int, r, width); /* insert top/bottom coordinates */ - line_list[ 2*i ] = my_min(int, t, height); - line_list[(2*i)+1] = my_min(int, b, height); + line_list[ 2*i ] = min_t(int, t, height); + line_list[(2*i)+1] = min_t(int, b, height); } /* sort and eliminate lists */ @@ -411,9 +407,9 @@ sort_and_eliminate( &line_list[0], &cnt_line ); /* calculate the number of used u32s */ - numdwords = my_max(int, (cnt_line+1), (cnt_pixel+1))*2; - numdwords = my_max(int, 4, numdwords); - numdwords = my_min(int, 64, numdwords); + numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2; + numdwords = max_t(int, 4, numdwords); + numdwords = min_t(int, 64, numdwords); /* fill up cliptable */ for(i = 0; i < cnt_pixel; i++) { @@ -1022,6 +1018,7 @@ saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field); saa7146_set_output_format(dev, sfmt->trans); + saa7146_disable_clipping(dev); if ( vv->last_field == V4L2_FIELD_INTERLACED ) { } else if ( vv->last_field == V4L2_FIELD_TOP ) { diff -urN linux-2.6.2-rc2/drivers/media/common/saa7146_video.c linux-2.6.2-rc3/drivers/media/common/saa7146_video.c --- linux-2.6.2-rc2/drivers/media/common/saa7146_video.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/common/saa7146_video.c 2004-01-30 18:49:21.000000000 -0800 @@ -755,7 +755,7 @@ dmas = MASK_22 | MASK_21 | MASK_20; } else { resource = RESOURCE_DMA1_HPS; - dmas = MASK_20; + dmas = MASK_22; } saa7146_res_free(fh, resource); @@ -1110,6 +1110,9 @@ DEB_D(("overlay is active, but in another open\n")); return -EAGAIN; } + } else { + DEB_D(("overlay is not active\n")); + return 0; } spin_lock_irqsave(&dev->slock,flags); err = saa7146_stop_preview(fh); diff -urN linux-2.6.2-rc2/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.6.2-rc3/drivers/media/dvb/dvb-core/dvb_frontend.c --- linux-2.6.2-rc2/drivers/media/dvb/dvb-core/dvb_frontend.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/dvb/dvb-core/dvb_frontend.c 2004-01-30 18:49:21.000000000 -0800 @@ -67,7 +67,7 @@ pid_t thread_pid; unsigned long release_jiffies; unsigned long lost_sync_jiffies; - int aquire_signal; + int acquire_signal; int bending; int lnb_drift; int timeout_count; @@ -306,7 +306,7 @@ fe->lost_sync_count = 0; fe->lost_sync_jiffies = jiffies; fe->lnb_drift = 0; - fe->aquire_signal = 1; + fe->acquire_signal = 1; if (fe->status & ~FE_TIMEDOUT) dvb_frontend_add_event (fe, 0); memcpy (&fe->parameters, param, @@ -467,13 +467,13 @@ if (s & FE_HAS_LOCK) { fe->timeout_count = 0; fe->lost_sync_count = 0; - fe->aquire_signal = 0; + fe->acquire_signal = 0; } else { fe->lost_sync_count++; if (!(fe->info->caps & FE_CAN_RECOVER)) { if (!(fe->info->caps & FE_CAN_CLEAN_SETUP)) { if (fe->lost_sync_count < 10) { - if (fe->aquire_signal) + if (fe->acquire_signal) dvb_frontend_internal_ioctl( &fe->frontend, FE_RESET, NULL); diff -urN linux-2.6.2-rc2/drivers/media/dvb/frontends/alps_tdmb7.c linux-2.6.2-rc3/drivers/media/dvb/frontends/alps_tdmb7.c --- linux-2.6.2-rc2/drivers/media/dvb/frontends/alps_tdmb7.c 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/dvb/frontends/alps_tdmb7.c 2004-01-30 18:49:21.000000000 -0800 @@ -374,7 +374,7 @@ cx22700_set_inversion (i2c, p->inversion); cx22700_set_tps (i2c, &p->u.ofdm); cx22700_writereg (i2c, 0x37, 0x01); /* PAL loop filter off */ - cx22700_writereg (i2c, 0x00, 0x01); /* restart aquire */ + cx22700_writereg (i2c, 0x00, 0x01); /* restart acquire */ break; } diff -urN linux-2.6.2-rc2/drivers/media/dvb/frontends/nxt6000.c linux-2.6.2-rc3/drivers/media/dvb/frontends/nxt6000.c --- linux-2.6.2-rc2/drivers/media/dvb/frontends/nxt6000.c 2004-01-08 22:59:47.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/dvb/frontends/nxt6000.c 2004-01-30 18:49:21.000000000 -0800 @@ -123,7 +123,19 @@ struct nxt6000_config *nxt = FE2NXT(fe); return nxt6000_read(fe->i2c, nxt->demod_addr, reg); +} + +static int pll_test(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr) +{ + u8 buf [1]; + struct i2c_msg msg = {.addr = tuner_addr >> 1,.flags = I2C_M_RD,.buf = buf,.len = 1 }; + int ret; + nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ + ret = i2c->xfer(i2c, &msg, 1); + nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ + + return (ret != 1) ? -EFAULT : 0; } static int pll_write(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr, u8 *buf, u8 len) @@ -833,21 +845,21 @@ if (nxt6000_read(i2c, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE) continue; - if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) { + if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) { nxt->tuner_addr = 0xC0; nxt->tuner_type = TUNER_TYPE_ALP510; nxt->clock_inversion = 1; dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr); - } else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC2, NULL, 0) == 0) { + } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC2) == 0) { nxt->tuner_addr = 0xC2; nxt->tuner_type = TUNER_TYPE_SP5659; nxt->clock_inversion = 0; dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr); - } else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) { + } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) { nxt->tuner_addr = 0xC0; nxt->tuner_type = TUNER_TYPE_SP5730; nxt->clock_inversion = 0; diff -urN linux-2.6.2-rc2/drivers/media/dvb/ttpci/Kconfig linux-2.6.2-rc3/drivers/media/dvb/ttpci/Kconfig --- linux-2.6.2-rc2/drivers/media/dvb/ttpci/Kconfig 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/dvb/ttpci/Kconfig 2004-01-30 18:49:21.000000000 -0800 @@ -66,6 +66,9 @@ (so called Budget- or Nova-PCI cards) without onboard MPEG2 decoder, but with onboard Common Interface connector. + Note: The Common Interface is not yet supported by this driver + due to lack of information from the vendor. + Say Y if you own such a card and want to use it. To compile this driver as a module, choose M here: the diff -urN linux-2.6.2-rc2/drivers/media/dvb/ttusb-dec/Kconfig linux-2.6.2-rc3/drivers/media/dvb/ttusb-dec/Kconfig --- linux-2.6.2-rc2/drivers/media/dvb/ttusb-dec/Kconfig 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/dvb/ttusb-dec/Kconfig 2004-01-30 18:49:21.000000000 -0800 @@ -2,6 +2,7 @@ tristate "Technotrend/Hauppauge USB DEC devices" depends on DVB_CORE && USB select FW_LOADER + select CRC32 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'DEC2000-t' diff -urN linux-2.6.2-rc2/drivers/media/dvb/ttusb-dec/ttusb_dec.c linux-2.6.2-rc3/drivers/media/dvb/ttusb-dec/ttusb_dec.c --- linux-2.6.2-rc2/drivers/media/dvb/ttusb-dec/ttusb_dec.c 2004-01-30 18:49:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/media/dvb/ttusb-dec/ttusb_dec.c 2004-01-30 18:49:21.000000000 -0800 @@ -552,13 +552,14 @@ break; case 3: - if (*b++ == 0x00) { + if (*b == 0x00) { dec->packet_state++; dec->packet_length = 0; - } else { + } else if (*b != 0xaa) { dec->packet_state = 0; } + b++; length--; break; diff -urN linux-2.6.2-rc2/drivers/mtd/maps/sa1100-flash.c linux-2.6.2-rc3/drivers/mtd/maps/sa1100-flash.c --- linux-2.6.2-rc2/drivers/mtd/maps/sa1100-flash.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/mtd/maps/sa1100-flash.c 2004-01-30 18:49:21.000000000 -0800 @@ -154,50 +154,34 @@ #ifdef CONFIG_SA1100_CERF #ifdef CONFIG_SA1100_CERF_FLASH_32MB -static struct mtd_partition cerf_partitions[] = { - { - .name = "firmware", - .size = 0x00040000, - .offset = 0, - }, { - .name = "params", - .size = 0x00040000, - .offset = 0x00040000, - }, { - .name = "kernel", - .size = 0x00100000, - .offset = 0x00080000, - }, { - .name = "rootdisk", - .size = 0x01E80000, - .offset = 0x00180000, - } -}; +# define CERF_FLASH_SIZE 0x02000000 #elif defined CONFIG_SA1100_CERF_FLASH_16MB +# define CERF_FLASH_SIZE 0x01000000 +#elif defined CONFIG_SA1100_CERF_FLASH_8MB +# define CERF_FLASH_SIZE 0x00800000 +#else +# error "Undefined flash size for CERF in sa1100-flash.c" +#endif + static struct mtd_partition cerf_partitions[] = { { - .name = "firmware", + .name = "Bootloader", .size = 0x00020000, - .offset = 0, + .offset = 0x00000000, }, { - .name = "params", - .size = 0x00020000, + .name = "Params", + .size = 0x00040000, .offset = 0x00020000, }, { - .name = "kernel", + .name = "Kernel", .size = 0x00100000, - .offset = 0x00040000, + .offset = 0x00060000, }, { - .name = "rootdisk", - .size = 0x00EC0000, - .offset = 0x00140000, + .name = "Filesystem", + .size = CERF_FLASH_SIZE-0x00160000, + .offset = 0x00160000, } }; -#elif defined CONFIG_SA1100_CERF_FLASH_8MB -# error "Unwritten type definition" -#else -# error "Undefined memory orientation for CERF in sa1100-flash.c" -#endif #endif #ifdef CONFIG_SA1100_CONSUS diff -urN linux-2.6.2-rc2/drivers/net/irda/act200l-sir.c linux-2.6.2-rc3/drivers/net/irda/act200l-sir.c --- linux-2.6.2-rc2/drivers/net/irda/act200l-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/act200l-sir.c 2004-01-30 18:49:21.000000000 -0800 @@ -93,12 +93,12 @@ .set_speed = act200l_change_speed, }; -int __init act200l_init(void) +static int __init act200l_init(void) { return irda_register_dongle(&act200l); } -void __exit act200l_cleanup(void) +static void __exit act200l_cleanup(void) { irda_unregister_dongle(&act200l); } diff -urN linux-2.6.2-rc2/drivers/net/irda/act200l.c linux-2.6.2-rc3/drivers/net/irda/act200l.c --- linux-2.6.2-rc2/drivers/net/irda/act200l.c 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/act200l.c 2004-01-30 18:49:21.000000000 -0800 @@ -92,12 +92,12 @@ .owner = THIS_MODULE, }; -int __init act200l_init(void) +static int __init act200l_init(void) { return irda_device_register_dongle(&dongle); } -void __exit act200l_cleanup(void) +static void __exit act200l_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/actisys-sir.c linux-2.6.2-rc3/drivers/net/irda/actisys-sir.c --- linux-2.6.2-rc2/drivers/net/irda/actisys-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/actisys-sir.c 2004-01-30 18:49:21.000000000 -0800 @@ -89,7 +89,7 @@ .set_speed = actisys_change_speed, }; -int __init actisys_sir_init(void) +static int __init actisys_sir_init(void) { int ret; @@ -107,7 +107,7 @@ return 0; } -void __exit actisys_sir_cleanup(void) +static void __exit actisys_sir_cleanup(void) { /* We have to remove both dongles */ irda_unregister_dongle(&act220l_plus); diff -urN linux-2.6.2-rc2/drivers/net/irda/actisys.c linux-2.6.2-rc3/drivers/net/irda/actisys.c --- linux-2.6.2-rc2/drivers/net/irda/actisys.c 2004-01-08 23:00:14.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/actisys.c 2004-01-30 18:49:21.000000000 -0800 @@ -91,7 +91,7 @@ * So, we register a dongle of each sort and let irattach * pick the right one... */ -int __init actisys_init(void) +static int __init actisys_init(void) { int ret; @@ -108,7 +108,7 @@ return 0; } -void __exit actisys_cleanup(void) +static void __exit actisys_cleanup(void) { /* We have to remove both dongles */ irda_device_unregister_dongle(&dongle); diff -urN linux-2.6.2-rc2/drivers/net/irda/ali-ircc.c linux-2.6.2-rc3/drivers/net/irda/ali-ircc.c --- linux-2.6.2-rc2/drivers/net/irda/ali-ircc.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/ali-ircc.c 2004-01-30 18:49:21.000000000 -0800 @@ -133,7 +133,7 @@ * Initialize chip. Find out whay kinds of chips we are dealing with * and their configuation registers address */ -int __init ali_ircc_init(void) +static int __init ali_ircc_init(void) { ali_chip_t *chip; chipio_t info; diff -urN linux-2.6.2-rc2/drivers/net/irda/ep7211_ir.c linux-2.6.2-rc3/drivers/net/irda/ep7211_ir.c --- linux-2.6.2-rc2/drivers/net/irda/ep7211_ir.c 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/ep7211_ir.c 2004-01-30 18:49:21.000000000 -0800 @@ -97,7 +97,7 @@ * Initialize EP7211 I/R module * */ -int __init ep7211_ir_init(void) +static int __init ep7211_ir_init(void) { return irda_device_register_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/esi.c linux-2.6.2-rc3/drivers/net/irda/esi.c --- linux-2.6.2-rc2/drivers/net/irda/esi.c 2004-01-08 22:59:42.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/esi.c 2004-01-30 18:49:21.000000000 -0800 @@ -52,12 +52,12 @@ .owner = THIS_MODULE, }; -int __init esi_init(void) +static int __init esi_init(void) { return irda_device_register_dongle(&dongle); } -void __exit esi_cleanup(void) +static void __exit esi_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/girbil-sir.c linux-2.6.2-rc3/drivers/net/irda/girbil-sir.c --- linux-2.6.2-rc2/drivers/net/irda/girbil-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/girbil-sir.c 2004-01-30 18:49:21.000000000 -0800 @@ -72,12 +72,12 @@ .set_speed = girbil_change_speed, }; -int __init girbil_init(void) +static int __init girbil_init(void) { return irda_register_dongle(&girbil); } -void __exit girbil_cleanup(void) +static void __exit girbil_cleanup(void) { irda_unregister_dongle(&girbil); } diff -urN linux-2.6.2-rc2/drivers/net/irda/girbil.c linux-2.6.2-rc3/drivers/net/irda/girbil.c --- linux-2.6.2-rc2/drivers/net/irda/girbil.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/girbil.c 2004-01-30 18:49:21.000000000 -0800 @@ -71,12 +71,12 @@ .owner = THIS_MODULE, }; -int __init girbil_init(void) +static int __init girbil_init(void) { return irda_device_register_dongle(&dongle); } -void __exit girbil_cleanup(void) +static void __exit girbil_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/irport.c linux-2.6.2-rc3/drivers/net/irda/irport.c --- linux-2.6.2-rc2/drivers/net/irda/irport.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/irport.c 2004-01-30 18:49:21.000000000 -0800 @@ -98,7 +98,7 @@ EXPORT_SYMBOL(irport_net_open); EXPORT_SYMBOL(irport_net_close); -int __init irport_init(void) +static int __init irport_init(void) { int i; diff -urN linux-2.6.2-rc2/drivers/net/irda/litelink-sir.c linux-2.6.2-rc3/drivers/net/irda/litelink-sir.c --- linux-2.6.2-rc2/drivers/net/irda/litelink-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/litelink-sir.c 2004-01-30 18:49:21.000000000 -0800 @@ -64,12 +64,12 @@ .set_speed = litelink_change_speed, }; -int __init litelink_sir_init(void) +static int __init litelink_sir_init(void) { return irda_register_dongle(&litelink); } -void __exit litelink_sir_cleanup(void) +static void __exit litelink_sir_cleanup(void) { irda_unregister_dongle(&litelink); } diff -urN linux-2.6.2-rc2/drivers/net/irda/litelink.c linux-2.6.2-rc3/drivers/net/irda/litelink.c --- linux-2.6.2-rc2/drivers/net/irda/litelink.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/litelink.c 2004-01-30 18:49:21.000000000 -0800 @@ -56,12 +56,12 @@ .owner = THIS_MODULE, }; -int __init litelink_init(void) +static int __init litelink_init(void) { return irda_device_register_dongle(&dongle); } -void __exit litelink_cleanup(void) +static void __exit litelink_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/ma600-sir.c linux-2.6.2-rc3/drivers/net/irda/ma600-sir.c --- linux-2.6.2-rc2/drivers/net/irda/ma600-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/ma600-sir.c 2004-01-30 18:49:21.000000000 -0800 @@ -66,13 +66,13 @@ }; -int __init ma600_sir_init(void) +static int __init ma600_sir_init(void) { IRDA_DEBUG(2, "%s()\n", __FUNCTION__); return irda_register_dongle(&ma600); } -void __exit ma600_sir_cleanup(void) +static void __exit ma600_sir_cleanup(void) { IRDA_DEBUG(2, "%s()\n", __FUNCTION__); irda_unregister_dongle(&ma600); diff -urN linux-2.6.2-rc2/drivers/net/irda/ma600.c linux-2.6.2-rc3/drivers/net/irda/ma600.c --- linux-2.6.2-rc2/drivers/net/irda/ma600.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/ma600.c 2004-01-30 18:49:21.000000000 -0800 @@ -82,13 +82,13 @@ .owner = THIS_MODULE, }; -int __init ma600_init(void) +static int __init ma600_init(void) { IRDA_DEBUG(2, "%s()\n", __FUNCTION__); return irda_device_register_dongle(&dongle); } -void __exit ma600_cleanup(void) +static void __exit ma600_cleanup(void) { IRDA_DEBUG(2, "%s()\n", __FUNCTION__); irda_device_unregister_dongle(&dongle); diff -urN linux-2.6.2-rc2/drivers/net/irda/mcp2120-sir.c linux-2.6.2-rc3/drivers/net/irda/mcp2120-sir.c --- linux-2.6.2-rc2/drivers/net/irda/mcp2120-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/mcp2120-sir.c 2004-01-30 18:49:21.000000000 -0800 @@ -49,12 +49,12 @@ .set_speed = mcp2120_change_speed, }; -int __init mcp2120_init(void) +static int __init mcp2120_init(void) { return irda_register_dongle(&mcp2120); } -void __exit mcp2120_cleanup(void) +static void __exit mcp2120_cleanup(void) { irda_unregister_dongle(&mcp2120); } diff -urN linux-2.6.2-rc2/drivers/net/irda/mcp2120.c linux-2.6.2-rc3/drivers/net/irda/mcp2120.c --- linux-2.6.2-rc2/drivers/net/irda/mcp2120.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/mcp2120.c 2004-01-30 18:49:21.000000000 -0800 @@ -48,12 +48,12 @@ .owner = THIS_MODULE, }; -int __init mcp2120_init(void) +static int __init mcp2120_init(void) { return irda_device_register_dongle(&dongle); } -void __exit mcp2120_cleanup(void) +static void __exit mcp2120_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/nsc-ircc.c linux-2.6.2-rc3/drivers/net/irda/nsc-ircc.c --- linux-2.6.2-rc2/drivers/net/irda/nsc-ircc.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/nsc-ircc.c 2004-01-30 18:49:22.000000000 -0800 @@ -155,7 +155,7 @@ * Initialize chip. Just try to find out how many chips we are dealing with * and where they are */ -int __init nsc_ircc_init(void) +static int __init nsc_ircc_init(void) { chipio_t info; nsc_chip_t *chip; diff -urN linux-2.6.2-rc2/drivers/net/irda/old_belkin-sir.c linux-2.6.2-rc3/drivers/net/irda/old_belkin-sir.c --- linux-2.6.2-rc2/drivers/net/irda/old_belkin-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/old_belkin-sir.c 2004-01-30 18:49:22.000000000 -0800 @@ -78,12 +78,12 @@ .set_speed = old_belkin_change_speed, }; -int __init old_belkin_init(void) +static int __init old_belkin_init(void) { return irda_register_dongle(&old_belkin); } -void __exit old_belkin_cleanup(void) +static void __exit old_belkin_cleanup(void) { irda_unregister_dongle(&old_belkin); } diff -urN linux-2.6.2-rc2/drivers/net/irda/old_belkin.c linux-2.6.2-rc3/drivers/net/irda/old_belkin.c --- linux-2.6.2-rc2/drivers/net/irda/old_belkin.c 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/old_belkin.c 2004-01-30 18:49:22.000000000 -0800 @@ -82,12 +82,12 @@ .owner = THIS_MODULE, }; -int __init old_belkin_init(void) +static int __init old_belkin_init(void) { return irda_device_register_dongle(&dongle); } -void __exit old_belkin_cleanup(void) +static void __exit old_belkin_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/smsc-ircc2.c linux-2.6.2-rc3/drivers/net/irda/smsc-ircc2.c --- linux-2.6.2-rc2/drivers/net/irda/smsc-ircc2.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/smsc-ircc2.c 2004-01-30 18:49:22.000000000 -0800 @@ -322,7 +322,7 @@ * Initialize chip. Just try to find out how many chips we are dealing with * and where they are */ -int __init smsc_ircc_init(void) +static int __init smsc_ircc_init(void) { int ret=-ENODEV; @@ -1727,7 +1727,7 @@ return 0; } -void __exit smsc_ircc_cleanup(void) +static void __exit smsc_ircc_cleanup(void) { int i; diff -urN linux-2.6.2-rc2/drivers/net/irda/tekram-sir.c linux-2.6.2-rc3/drivers/net/irda/tekram-sir.c --- linux-2.6.2-rc2/drivers/net/irda/tekram-sir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/tekram-sir.c 2004-01-30 18:49:22.000000000 -0800 @@ -59,7 +59,7 @@ .set_speed = tekram_change_speed, }; -int __init tekram_sir_init(void) +static int __init tekram_sir_init(void) { if (tekram_delay < 1 || tekram_delay > 500) tekram_delay = 200; @@ -68,7 +68,7 @@ return irda_register_dongle(&tekram); } -void __exit tekram_sir_cleanup(void) +static void __exit tekram_sir_cleanup(void) { irda_unregister_dongle(&tekram); } diff -urN linux-2.6.2-rc2/drivers/net/irda/tekram.c linux-2.6.2-rc3/drivers/net/irda/tekram.c --- linux-2.6.2-rc2/drivers/net/irda/tekram.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/tekram.c 2004-01-30 18:49:22.000000000 -0800 @@ -52,12 +52,12 @@ .owner = THIS_MODULE, }; -int __init tekram_init(void) +static int __init tekram_init(void) { return irda_device_register_dongle(&dongle); } -void __exit tekram_cleanup(void) +static void __exit tekram_cleanup(void) { irda_device_unregister_dongle(&dongle); } diff -urN linux-2.6.2-rc2/drivers/net/irda/via-ircc.c linux-2.6.2-rc3/drivers/net/irda/via-ircc.c --- linux-2.6.2-rc2/drivers/net/irda/via-ircc.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/via-ircc.c 2004-01-30 18:49:22.000000000 -0800 @@ -145,7 +145,7 @@ * * Initialize chip. Just find out chip type and resource. */ -int __init via_ircc_init(void) +static int __init via_ircc_init(void) { int rc; diff -urN linux-2.6.2-rc2/drivers/net/irda/w83977af_ir.c linux-2.6.2-rc3/drivers/net/irda/w83977af_ir.c --- linux-2.6.2-rc2/drivers/net/irda/w83977af_ir.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/irda/w83977af_ir.c 2004-01-30 18:49:22.000000000 -0800 @@ -110,7 +110,7 @@ * Initialize chip. Just try to find out how many chips we are dealing with * and where they are */ -int __init w83977af_init(void) +static int __init w83977af_init(void) { int i; @@ -129,7 +129,7 @@ * Close all configured chips * */ -void __exit w83977af_cleanup(void) +static void __exit w83977af_cleanup(void) { int i; diff -urN linux-2.6.2-rc2/drivers/net/wan/pc300_drv.c linux-2.6.2-rc3/drivers/net/wan/pc300_drv.c --- linux-2.6.2-rc2/drivers/net/wan/pc300_drv.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/net/wan/pc300_drv.c 2004-01-30 18:49:22.000000000 -0800 @@ -6,9 +6,9 @@ * pc300.c Cyclades-PC300(tm) Driver. * * Author: Ivan Passos - * Maintainer: Henrique Gobbi + * Maintainer: PC300 Maintainer * - * Copyright: (c) 1999-2002 Cyclades Corp. + * Copyright: (c) 1999-2003 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -252,7 +252,7 @@ #undef PC300_DEBUG_RX #undef PC300_DEBUG_OTHER -static struct pci_device_id cpc_pci_dev_id[] = { +static struct pci_device_id cpc_pci_dev_id[] __devinitdata = { /* PC300/RSV or PC300/X21, 2 chan */ {0x120e, 0x300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x300}, /* PC300/RSV or PC300/X21, 1 chan */ @@ -1961,7 +1961,7 @@ } stats->rx_packets++; skb->mac.raw = skb->data; - skb->protocol = htons(ETH_P_HDLC); + skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } } @@ -2088,9 +2088,10 @@ } } if (!(dsr_rx = cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { - -printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n", - dev->name, ch, status, drx_stat, dsr_rx); +#ifdef PC300_DEBUG_INTR + printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n", + dev->name, ch, status, drx_stat, dsr_rx); +#endif cpc_writeb(scabase + DSR_RX(ch), (dsr_rx | DSR_DE) & 0xfe); } } @@ -2770,6 +2771,10 @@ if (!capable(CAP_NET_ADMIN)) { return -EPERM; } + /* incorrect data len? */ + if (ifr->ifr_settings.size != size) { + return -ENOBUFS; + } if (copy_from_user(&conf->phys_settings, settings->ifs_ifsu.sync, size)) { @@ -2788,12 +2793,18 @@ case IF_IFACE_T1: case IF_IFACE_E1: { + const size_t te_size = sizeof(te1_settings); const size_t size = sizeof(sync_serial_settings); if (!capable(CAP_NET_ADMIN)) { return -EPERM; } - + + /* incorrect data len? */ + if (ifr->ifr_settings.size != te_size) { + return -ENOBUFS; + } + if (copy_from_user(&conf->phys_settings, settings->ifs_ifsu.te1, size)) { return -EFAULT; @@ -3667,12 +3678,10 @@ } static struct pci_driver cpc_driver = { - .name = "pc300", - .id_table = cpc_pci_dev_id, - .probe = cpc_init_one, - .remove = cpc_remove_one, - .suspend = NULL, - .resume = NULL, + .name = "pc300", + .id_table = cpc_pci_dev_id, + .probe = cpc_init_one, + .remove = __devexit_p(cpc_remove_one), }; static int __init cpc_init(void) @@ -3690,6 +3699,6 @@ MODULE_DESCRIPTION("Cyclades-PC300 cards driver"); MODULE_AUTHOR( "Author: Ivan Passos \r\n" - "Maintainer: Henrique Gobbi subordinate->node, &dev->bus->children); spin_unlock(&pci_bus_lock); pci_bus_add_devices(dev->subordinate); + + sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge"); } } } diff -urN linux-2.6.2-rc2/drivers/pci/gen-devlist.c linux-2.6.2-rc3/drivers/pci/gen-devlist.c --- linux-2.6.2-rc2/drivers/pci/gen-devlist.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/gen-devlist.c 2004-01-30 18:49:22.000000000 -0800 @@ -7,12 +7,13 @@ #include #include -#define MAX_NAME_SIZE 79 +#define MAX_NAME_SIZE 89 static void -pq(FILE *f, const char *c) +pq(FILE *f, const char *c, int len) { - while (*c) { + int i = 1; + while (*c && i != len) { if (*c == '"') fprintf(f, "\\\""); else { @@ -23,6 +24,7 @@ } } c++; + i++; } } @@ -72,13 +74,13 @@ if (bra && bra > c && bra[-1] == ' ') bra[-1] = 0; if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) { - fprintf(stderr, "Line %d: Device name too long\n", lino); + fprintf(stderr, "Line %d: Device name too long. Name truncated.\n", lino); fprintf(stderr, "%s\n", c); - return 1; + /*return 1;*/ } } fprintf(devf, "\tDEVICE(%s,%s,\"", vend, line+1); - pq(devf, c); + pq(devf, c, MAX_NAME_SIZE - vendor_len - 1); fputs("\")\n", devf); } else goto err; break; @@ -107,7 +109,7 @@ return 1; } fprintf(devf, "VENDOR(%s,\"", vend); - pq(devf, c); + pq(devf, c, 0); fputs("\")\n", devf); mode = 1; } else { diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp.h linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp.h --- linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp.h 2004-01-08 23:00:12.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp.h 2004-01-30 18:49:22.000000000 -0800 @@ -201,7 +201,7 @@ #define SLOT_POWEREDON (0x00000001) #define SLOT_ENABLED (0x00000002) -#define SLOT_MULTIFUNCTION (x000000004) +#define SLOT_MULTIFUNCTION (0x00000004) /* function flags */ @@ -212,8 +212,6 @@ #define FUNC_HAS_PS2 (0x00000040) #define FUNC_HAS_PS3 (0x00000080) -#define FUNC_EXISTS (0x10000000) /* to make sure we call _EJ0 only for existing funcs */ - /* function prototypes */ /* acpiphp_glue.c */ @@ -231,6 +229,7 @@ extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); +extern u32 acpiphp_get_address (struct acpiphp_slot *slot); /* acpiphp_pci.c */ extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn); diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_core.c linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_core.c --- linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_core.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_core.c 2004-01-30 18:49:22.000000000 -0800 @@ -30,14 +30,14 @@ * */ -#include -#include +#include #include + +#include #include #include #include #include -#include #include "pci_hotplug.h" #include "acpiphp.h" @@ -71,6 +71,7 @@ static int hardware_test (struct hotplug_slot *slot, u32 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); @@ -86,6 +87,7 @@ .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, }; @@ -322,6 +324,28 @@ } +/** + * get_address - get pci address of a slot + * @hotplug_slot: slot to get status + * @busdev: pointer to struct pci_busdev (seg, bus, dev) + * + */ +static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_address(slot->acpi_slot); + + return retval; +} + + /* return dummy value because ACPI doesn't provide any method... */ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_glue.c linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_glue.c --- linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_glue.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_glue.c 2004-01-30 18:49:22.000000000 -0800 @@ -26,12 +26,12 @@ * */ -#include -#include +#include #include + +#include #include #include -#include #include #include "../pci.h" @@ -245,7 +245,9 @@ acpi_resource_to_address64(resource, &address); if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) { - dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, address.min_address_range, address.max_address_range); + dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, + (unsigned long long)address.min_address_range, + (unsigned long long)address.max_address_range); res = acpiphp_make_resource(address.min_address_range, address.address_length); if (!res) { @@ -684,7 +686,7 @@ struct list_head *l; int retval = 0; - /* is this already enabled? */ + /* if already enabled, just skip */ if (slot->flags & SLOT_POWEREDON) goto err_exit; @@ -722,14 +724,14 @@ int retval = 0; - /* is this already enabled? */ + /* if already disabled, just skip */ if ((slot->flags & SLOT_POWEREDON) == 0) goto err_exit; list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); - if (func->flags & (FUNC_HAS_PS3 | FUNC_EXISTS)) { + if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) { status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); if (ACPI_FAILURE(status)) { warn("%s: _PS3 failed\n", __FUNCTION__); @@ -743,7 +745,7 @@ func = list_entry(l, struct acpiphp_func, sibling); /* We don't want to call _EJ0 on non-existing functions. */ - if (func->flags & (FUNC_HAS_EJ0 | FUNC_EXISTS)) { + if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) { /* _EJ0 method take one argument */ arg_list.count = 1; arg_list.pointer = &arg; @@ -756,7 +758,6 @@ retval = -1; goto err_exit; } - func->flags &= (~FUNC_EXISTS); } } @@ -836,8 +837,6 @@ retval = acpiphp_configure_function(func); if (retval) goto err_exit; - - func->flags |= FUNC_EXISTS; } slot->flags |= SLOT_ENABLED; @@ -974,6 +973,21 @@ dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); break; + case ACPI_NOTIFY_FREQUENCY_MISMATCH: + printk(KERN_ERR "Device %s cannot be configured due" + " to a frequency mismatch\n", objname); + break; + + case ACPI_NOTIFY_BUS_MODE_MISMATCH: + printk(KERN_ERR "Device %s cannot be configured due" + " to a bus mode mismatch\n", objname); + break; + + case ACPI_NOTIFY_POWER_FAULT: + printk(KERN_ERR "Device %s has suffered a power fault\n", + objname); + break; + default: warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); break; @@ -1332,3 +1346,18 @@ return (sta == 0) ? 0 : 1; } + + +/* + * pci address (seg/bus/dev) + */ +u32 acpiphp_get_address (struct acpiphp_slot *slot) +{ + u32 address; + + address = ((slot->bridge->seg) << 16) | + ((slot->bridge->bus) << 8) | + slot->device; + + return address; +} diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_pci.c linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_pci.c --- linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_pci.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_pci.c 2004-01-30 18:49:22.000000000 -0800 @@ -29,11 +29,11 @@ * */ -#include -#include +#include #include + +#include #include -#include #include #include "../pci.h" #include "pci_hotplug.h" diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_res.c linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_res.c --- linux-2.6.2-rc2/drivers/pci/hotplug/acpiphp_res.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/acpiphp_res.c 2004-01-30 18:49:22.000000000 -0800 @@ -29,7 +29,7 @@ * */ -#include +#include #include #include @@ -39,7 +39,6 @@ #include #include #include -#include #include #include diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/cpcihp_zt5550.c linux-2.6.2-rc3/drivers/pci/hotplug/cpcihp_zt5550.c --- linux-2.6.2-rc2/drivers/pci/hotplug/cpcihp_zt5550.c 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/cpcihp_zt5550.c 2004-01-30 18:49:22.000000000 -0800 @@ -133,6 +133,8 @@ { if(!hc_dev) return -ENODEV; + + iounmap(hc_registers); release_mem_region(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1)); return 0; diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/pci_hotplug.h linux-2.6.2-rc3/drivers/pci/hotplug/pci_hotplug.h --- linux-2.6.2-rc2/drivers/pci/hotplug/pci_hotplug.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/pci_hotplug.h 2004-01-30 18:49:22.000000000 -0800 @@ -74,6 +74,9 @@ * @get_adapter_status: Called to get see if an adapter is present in the slot or not. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. + * @get_address: Called to get pci address of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. * @get_max_bus_speed: Called to get the max bus speed for a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. @@ -96,6 +99,7 @@ int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); + int (*get_address) (struct hotplug_slot *slot, u32 *value); int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); }; @@ -106,6 +110,7 @@ * @attention_status: if the attention light is enabled or not (1/0) * @latch_status: if the latch (if any) is open or closed (1/0) * @adapter_present: if there is a pci board present in the slot or not (1/0) + * @address: (domain << 16 | bus << 8 | dev) * * Used to notify the hotplug pci core of the status of a specific slot. */ @@ -114,6 +119,7 @@ u8 attention_status; u8 latch_status; u8 adapter_status; + u32 address; enum pci_bus_speed max_bus_speed; enum pci_bus_speed cur_bus_speed; }; diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/pci_hotplug_core.c linux-2.6.2-rc3/drivers/pci/hotplug/pci_hotplug_core.c --- linux-2.6.2-rc2/drivers/pci/hotplug/pci_hotplug_core.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/pci_hotplug_core.c 2004-01-30 18:49:22.000000000 -0800 @@ -159,6 +159,7 @@ GET_STATUS(attention_status, u8) GET_STATUS(latch_status, u8) GET_STATUS(adapter_status, u8) +GET_STATUS(address, u32) GET_STATUS(max_bus_speed, enum pci_bus_speed) GET_STATUS(cur_bus_speed, enum pci_bus_speed) @@ -302,6 +303,28 @@ .show = presence_read_file, }; +static ssize_t address_read_file (struct hotplug_slot *slot, char *buf) +{ + int retval; + u32 address; + + retval = get_address (slot, &address); + if (retval) + goto exit; + retval = sprintf (buf, "%04x:%02x:%02x\n", + (address >> 16) & 0xffff, + (address >> 8) & 0xff, + address & 0xff); + +exit: + return retval; +} + +static struct hotplug_slot_attribute hotplug_slot_attr_address = { + .attr = {.name = "address", .mode = S_IFREG | S_IRUGO}, + .show = address_read_file, +}; + static char *unknown_speed = "Unknown bus speed"; static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf) @@ -425,6 +448,15 @@ return -ENOENT; } +static int has_address_file (struct hotplug_slot *slot) +{ + if ((!slot) || (!slot->ops)) + return -ENODEV; + if (slot->ops->get_address) + return 0; + return -ENOENT; +} + static int has_max_bus_speed_file (struct hotplug_slot *slot) { if ((!slot) || (!slot->ops)) @@ -466,6 +498,9 @@ if (has_adapter_file(slot) == 0) sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if (has_address_file(slot) == 0) + sysfs_create_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if (has_max_bus_speed_file(slot) == 0) sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); @@ -492,6 +527,9 @@ if (has_adapter_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if (has_address_file(slot) == 0) + sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if (has_max_bus_speed_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); @@ -533,7 +571,7 @@ if ((slot->info == NULL) || (slot->ops == NULL)) return -EINVAL; - strlcpy(slot->kobj.name, slot->name, KOBJ_NAME_LEN); + kobject_set_name(&slot->kobj, slot->name); kobj_set_kset_s(slot, pci_hotplug_slots_subsys); /* this can fail if we have already registered a slot with the same name */ @@ -612,6 +650,10 @@ (slot->info->adapter_status != info->adapter_status)) sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if ((has_address_file(slot) == 0) && + (slot->info->address != info->address)) + sysfs_update_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if ((has_max_bus_speed_file(slot) == 0) && (slot->info->max_bus_speed != info->max_bus_speed)) sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); diff -urN linux-2.6.2-rc2/drivers/pci/hotplug/pcihp_skeleton.c linux-2.6.2-rc3/drivers/pci/hotplug/pcihp_skeleton.c --- linux-2.6.2-rc2/drivers/pci/hotplug/pcihp_skeleton.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/hotplug/pcihp_skeleton.c 2004-01-30 18:49:22.000000000 -0800 @@ -370,10 +370,10 @@ * Initilize the slot info structure with some known * good values. */ - info->power_status = get_skel_power_status(slot); - info->attention_status = get_skel_attention_status(slot); - info->latch_status = get_skel_latch_status(slot); - info->adapter_status = get_skel_adapter_status(slot); + info->power_status = get_power_status(slot); + info->attention_status = get_attention_status(slot); + info->latch_status = get_latch_status(slot); + info->adapter_status = get_adapter_status(slot); dbg ("registering slot %d\n", i); retval = pci_hp_register (slot->hotplug_slot); diff -urN linux-2.6.2-rc2/drivers/pci/names.c linux-2.6.2-rc3/drivers/pci/names.c --- linux-2.6.2-rc2/drivers/pci/names.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/names.c 2004-01-30 18:49:22.000000000 -0800 @@ -86,8 +86,7 @@ /* Full match */ match_device: { - char *n = name + sprintf(name, "%." PCI_NAME_HALF - "s %." PCI_NAME_HALF "s", + char *n = name + sprintf(name, "%s %s", vendor_p->name, device_p->name); int nr = device_p->seen + 1; device_p->seen = nr; diff -urN linux-2.6.2-rc2/drivers/pci/pci-sysfs.c linux-2.6.2-rc3/drivers/pci/pci-sysfs.c --- linux-2.6.2-rc2/drivers/pci/pci-sysfs.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/pci-sysfs.c 2004-01-30 18:49:22.000000000 -0800 @@ -160,6 +160,7 @@ .attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, }, .size = 256, .read = pci_read_config, diff -urN linux-2.6.2-rc2/drivers/pci/pci.ids linux-2.6.2-rc3/drivers/pci/pci.ids --- linux-2.6.2-rc2/drivers/pci/pci.ids 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/pci.ids 2004-01-30 18:49:22.000000000 -0800 @@ -7,7 +7,7 @@ # so if you have anything to contribute, please visit the home page or # send a diff -u against the most recent pci.ids to pci-ids@ucw.cz. # -# $Id: pci.ids,v 1.48 2002/12/26 13:03:41 mares Exp $ +# Daily snapshot on Wed 2004-01-14 11:00:17 # # Vendors, devices and subsystems. Please keep sorted. @@ -118,6 +118,8 @@ 0e11 7004 Embedded Ultra Wide SCSI Controller 1092 8760 FirePort 40 Dual SCSI Controller 1de1 3904 DC390F Ultra Wide SCSI Controller + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1050 CT7 mainboard 0010 53c895 0e11 4040 Integrated Array Controller 0e11 4048 Integrated Array Controller @@ -126,7 +128,10 @@ 0020 53c1010 Ultra3 SCSI Adapter 1de1 1020 DC-390U3W 0021 53c1010 66MHz Ultra3 SCSI Adapter - 0030 53c1030 + 4c53 1080 CT8 mainboard + 4c53 1300 P017 mezzanine (32-bit PMC) + 4c53 1310 P017 mezzanine (64-bit PMC) + 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI 1028 1010 LSI U320 SCSI Controller 0040 53c1035 008f 53c875J @@ -161,10 +166,17 @@ 0017 PROTO-3 PCI Prototyping board 9100 INI-9100/9100W SCSI Host 1002 ATI Technologies Inc + 4136 Radeon IGP 320 M + 4144 Radeon R300 AD [Radeon 9500 Pro] + 4145 Radeon R300 AE [Radeon 9500 Pro] + 4146 Radeon R300 AF [Radeon 9500 Pro] + 4147 Radeon R300 AG [FireGL Z1/X1] 4158 68800AX [Mach32] + 4164 Radeon R300 Secondary (DVI) output 4242 Radeon R200 BB [Radeon All in Wonder 8500DV] 1002 02aa Radeon 8500 AIW DV Edition 4336 Radeon Mobility U1 + 4337 Radeon IGP 340M 4354 215CT [Mach64 CT] 4358 210888CX [Mach64 CX] 4554 210888ET [Mach64 ET] @@ -214,6 +226,8 @@ 4752 Rage XL 1002 0008 Rage XL 1002 4752 Rage XL + 1002 8008 Rage XL + 1028 00ce PowerEdge 1400 1028 00d1 PowerEdge 2550 4753 Rage XC 1002 4753 Rage XC @@ -238,6 +252,8 @@ 10f1 0002 R250 If [Tachyon G9000 PRO] 148c 2039 R250 If [Radeon 9000 Pro "Evil Commando"] 1509 9a00 R250 If [Radeon 9000 "AT009"] +# New subdevice - 3D Prophet 9000 PCI by Hercules. AGP version probably would have same ID, so not specified. + 1681 0040 R250 If [3D prophet 9000] 174b 7176 R250 If [Sapphire Radeon 9000 Pro] 174b 7192 R250 If [Radeon 9000 "Atlantis"] 17af 2005 R250 If [Excalibur Radeon 9000 Pro] @@ -255,6 +271,7 @@ 4c44 3D Rage LT Pro AGP-66 4c45 Rage Mobility M3 AGP 4c46 Rage Mobility M3 AGP 2x + 1028 00b1 Latitude C600 4c47 3D Rage LT-G 215LG 4c49 3D Rage LT Pro 1002 0004 Rage LT Pro @@ -262,8 +279,11 @@ 1002 0044 Rage LT Pro 1002 4c49 Rage LT Pro 4c4d Rage Mobility P/M AGP 2x + 0e11 b111 Armada M700 + 0e11 b160 Armada E500 1002 0084 Xpert 98 AGP 2X (Mobility) 1014 0154 ThinkPad A20m + 1028 00aa Latitude CPt 4c4e Rage Mobility L AGP 2x 4c50 3D Rage LT Pro 1002 4c50 Rage LT Pro @@ -274,23 +294,33 @@ 4c57 Radeon Mobility M7 LW [Radeon Mobility 7500] 1014 0517 ThinkPad T30 1028 00e6 Radeon Mobility M7 LW (Dell Inspiron 8100) - 4c58 Radeon Mobility M7 LX [Radeon Mobility FireGL 7800] + 144d c006 Radeon Mobility M7 LW in vpr Matrix 170B4 + 4c58 Radeon RV200 LX [Mobility FireGL 7800 M7] 4c59 Radeon Mobility M6 LY 1014 0235 ThinkPad A30p (2653-64G) 1014 0239 ThinkPad X22/X23/X24 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 4c5a Radeon Mobility M6 LZ - 4c64 Radeon R250 Ld [Radeon Mobility 9000] - 4c65 Radeon R250 Le [Radeon Mobility 9000] - 4c66 Radeon R250 Lf [Radeon Mobility 9000] - 4c67 Radeon R250 Lg [Radeon Mobility 9000] + 4c64 Radeon R250 Ld [Radeon Mobility 9000 M9] + 4c65 Radeon R250 Le [Radeon Mobility 9000 M9] + 4c66 Radeon R250 Lf [Radeon Mobility 9000 M9] + 4c67 Radeon R250 Lg [Radeon Mobility 9000 M9] +# Secondary chip to the Lf + 4c6e Radeon R250 Ln [Radeon Mobility 9000 M9] [Secondary] 4d46 Rage Mobility M4 AGP 4d4c Rage Mobility M4 AGP - 4e44 Radeon R300 ND [Radeon 9700] - 4e45 Radeon R300 NE [Radeon 9700] + 4e44 Radeon R300 ND [Radeon 9700 Pro] + 4e45 Radeon R300 NE [Radeon 9500 Pro] + 1002 0002 Radeon R300 NE [Radeon 9500 Pro] 4e46 Radeon R300 NF [Radeon 9700] - 4e47 Radeon R300 NG [Radeon 9700] - 4e64 Radeon R300 [Radeon 9700] (Secondary) + 4e47 Radeon R300 NG [FireGL X1] + 4e48 Radeon R350 [Radeon 9800] + 4e64 Radeon R300 [Radeon 9700 Pro] (Secondary) + 4e65 Radeon R300 [Radeon 9500 Pro] (Secondary) + 1002 0003 Radeon R300 NE [Radeon 9500 Pro] + 4e66 Radeon R300 [Radeon 9700] (Secondary) + 4e67 Radeon R300 [FireGL X1] (Secondary) + 4e68 Radeon R350 [Radeon 9800] (Secondary) 5041 Rage 128 PA/PRO 5042 Rage 128 PB/PRO AGP 2x 5043 Rage 128 PC/PRO AGP 4x @@ -327,7 +357,7 @@ 5056 Rage 128 PV/PRO TMDS 5057 Rage 128 PW/PRO AGP 2x TMDS 5058 Rage 128 PX/PRO AGP 4x TMDS - 5144 Radeon R100 QD [Radeon 64 DDR] + 5144 Radeon R100 QD [Radeon 7200] 1002 0008 Radeon 7000/Radeon VE 1002 0009 Radeon 7000/Radeon 1002 000a Radeon 7000/Radeon @@ -345,8 +375,10 @@ 5146 Radeon R100 QF 5147 Radeon R100 QG 5148 Radeon R200 QH [Radeon 8500] - 1002 0152 FireGL 8800 - 1002 0172 FireGL 8700 + 1002 010a FireGL 8800 64Mb + 1002 0152 FireGL 8800 128Mb + 1002 0162 FireGL 8700 32Mb + 1002 0172 FireGL 8700 64Mb 5149 Radeon R200 QI 514a Radeon R200 QJ 514b Radeon R200 QK @@ -355,6 +387,9 @@ 1002 013a Radeon 8500 148c 2026 R200 QL [Radeon 8500 Evil Master II Multi Display Edition] 174b 7149 Radeon R200 QL [Sapphire Radeon 8500 LE] + 514d Radeon R200 QM [Radeon 9100] + 514e Radeon R200 QN [Radeon 8500LE] + 514f Radeon R200 QO [Radeon 8500LE] 5157 Radeon RV200 QW [Radeon 7500] 1002 013a Radeon 7500 1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR] @@ -365,7 +400,7 @@ 174b 7161 Radeon RV200 QW [Radeon 7500 LE] 17af 0202 RV200 QW [Excalibur Radeon 7500LE] 5158 Radeon RV200 QX [Radeon 7500] - 5159 Radeon VE QY + 5159 Radeon RV100 QY [Radeon 7000/VE] 1002 000a Radeon 7000/Radeon VE 1002 000b Radeon 7000 1002 0038 Radeon 7000/Radeon VE @@ -377,11 +412,13 @@ 148c 2023 RV100 QY [Radeon 7000 Evil Master Multi-Display] 174b 7112 RV100 QY [Sapphire Radeon VE 7000] 1787 0202 RV100 QY [Excalibur Radeon 7000] - 515a Radeon VE QZ + 515a Radeon RV100 QZ [Radeon 7000/VE] 5168 Radeon R200 Qh 5169 Radeon R200 Qi 516a Radeon R200 Qj 516b Radeon R200 Qk +# This one is not in ATI documentation, but is in XFree86 source code + 516c Radeon R200 Ql 5245 Rage 128 RE/SG 1002 0008 Xpert 128 1002 0028 Rage 128 AIW @@ -401,6 +438,7 @@ 1002 0088 Xpert 99 5345 Rage 128 SE/4x 5346 Rage 128 SF/4x AGP 2x + 1002 0048 RAGE 128 16MB VGA TVOUT AMC PAL 5347 Rage 128 SG/4x AGP 4x 5348 Rage 128 SH 534b Rage 128 SK/4x @@ -431,7 +469,11 @@ 1002 5654 Mach64VT Reference 5655 264VT3 [Mach64 VT3] 5656 264VT4 [Mach64 VT4] - 700f U1/A3 AGP Bridge [IGP 320M] + 5961 Radeon RV280 [Radeon 9200] + 700f PCI Bridge [IGP 320M] + 7010 PCI Bridge [IGP 340M] + cab0 AGP Bridge [IGP 320M] + cab2 RS200/RS200M AGP Bridge [IGP 340M] 1003 ULSI Systems 0201 US201 1004 VLSI Technology Inc @@ -485,7 +527,14 @@ 0011 NS87560 National PCI System I/O 0012 USB Controller 0020 DP83815 (MacPhyter) Ethernet Controller + 1385 f311 FA311 / FA312 (FA311 with WoL HW) 0022 DP83820 10/100/1000 Ethernet Controller + 0028 CS5535 Host bridge + 002b CS5535 ISA bridge + 002d CS5535 IDE + 002e CS5535 Audio + 002f CS5535 USB + 0030 CS5535 Video 0500 SCx200 Bridge 0501 SCx200 SMI 0502 SCx200 IDE @@ -537,6 +586,7 @@ 0014 DECchip 21041 [Tulip Pass 3] 1186 0100 DE-530+ 0016 DGLPB [OPPO] + 0017 PV-PCI Graphics Controller (ZLXp-L) 0019 DECchip 21142/43 1011 500a DE500A Fast Ethernet 1011 500b DE500B Fast Ethernet @@ -567,6 +617,7 @@ 1374 0002 Cardbus Ethernet Card 10/100 1374 0007 Cardbus Ethernet Card 10/100 1374 0008 Cardbus Ethernet Card 10/100 + 1385 2100 FA510 1395 0001 10/100 Ethernet CardBus PC Card 13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200) 8086 0001 EtherExpress PRO/100 Mobile CardBus 32 @@ -585,7 +636,9 @@ 0e11 4051 Integrated Smart Array 0e11 4058 Integrated Smart Array 103c 10c2 Hewlett-Packard NetRAID-4M - 12d9 000a VoIP PCI Gateway + 12d9 000a IP Telephony card + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard 9005 0365 Adaptec 5400S 9005 1364 Dell PowerEdge RAID Controller 2 9005 1365 Dell PowerEdge RAID Controller 2 @@ -650,14 +703,17 @@ 001b GXT-150P 001c Carrera 001d 82G2675 - 0020 MCA + 0020 GXT1000 Graphics Adapter 0022 IBM27-82351 002d Python - 002e ServeRAID Controller +# [official name in AIX 5] + 002e SCSI RAID Adapter [ServeRAID] 1014 002e ServeRAID-3x 1014 022e ServeRAID-4H + 0031 2 Port Serial Adapter 0036 Miami 003a CPU to PCI Bridge + 003c GXT250P/GXT255P Graphics Adapter 003e 16/4 Token ring UTP/STP controller 1014 003e Token-Ring Adapter 1014 00cd Token-Ring Adapter + Wake-On-LAN @@ -675,23 +731,30 @@ 004f ATM Controller (14104f00) 0050 ATM Controller (14105000) 0053 25 MBit ATM Controller + 0054 GXT500P/GXT550P Graphics Adapter 0057 MPEG PCI Bridge 005c i82557B 10/100 + 005e GXT800P Graphics Adapter 007c ATM Controller (14107c00) 007d 3780IDSP [MWave] + 008e GXT3000P Graphics Adapter 0090 GXT 3000P 1014 008e GXT-3000P + 0091 SSA Adapter 0095 20H2999 PCI Docking Bridge 0096 Chukar chipset SCSI controller 1014 0097 iSeries 2778 DASD IOA 1014 0098 iSeries 2763 DASD IOA 1014 0099 iSeries 2748 DASD IOA + 009f PCI 4758 Cryptographic Accelerator 00a5 ATM Controller (1410a500) 00a6 ATM 155MBPS MM Controller (1410a600) 00b7 256-bit Graphics Rasterizer [Fire GL1] + 00b8 GXT2000P Graphics Adapter 00be ATM 622MBPS Controller (1410be00) 00dc Advanced Systems Management Adapter (ASMA) 00fc CPC710 Dual Bridge and Memory Controller (PCI-64) + 0104 Gigabit Ethernet-SX Adapter 0105 CPC710 Dual Bridge and Memory Controller (PCI-32) 010f Remote Supervisor Adapter (RSA) 0142 Yotta Video Compositor Input @@ -699,6 +762,14 @@ 0144 Yotta Video Compositor Output 1014 0145 Yotta Output Controller (ytout) 0156 405GP PLB to PCI Bridge + 015e 622Mbps ATM PCI Adapter + 0160 64bit/66MHz PCI ATM 155 MMF + 016e GXT4000P Graphics Adapter + 0170 GXT6000P Graphics Adapter + 017d GXT300P Graphics Adapter + 0180 Snipe chipset SCSI controller + 1014 0241 iSeries 2757 DASD IOA + 1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780) 01a7 PCI-X to PCI-X Bridge 01bd ServeRAID Controller 1014 01be ServeRAID-4M @@ -708,6 +779,19 @@ 1014 022e ServeRAID-4H 1014 0258 ServeRAID-5i 1014 0259 ServeRAID-5i + 01c1 64bit/66MHz PCI ATM 155 UTP + 01e6 Cryptographic Accelerator + 01ff 10/100 Mbps Ethernet + 0219 Multiport Serial Adapter + 1014 021a Dual RVX + 1014 0251 Internal Modem/RVX + 1014 0252 Quad Internal Modem + 021b GXT6500P Graphics Adapter + 021c GXT4500P Graphics Adapter + 0233 GXT135P Graphics Adapter + 0266 PCI-X Dual Channel SCSI + 0268 Gigabit Ethernet-SX Adapter (PCI-X) + 0269 10/100/1000 Base-TX Ethernet Adapter (PCI-X) 0302 XA-32 chipset [Summit] ffff MPIC-2 interrupt controller 1015 LSI Logic Corp of Canada @@ -770,9 +854,16 @@ 1259 2454 AT-2450v4 10Mb Ethernet Adapter 1259 2700 AT-2700TX 10/100 Fast Ethernet 1259 2701 AT-2700FX 100Mb Ethernet + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1010 CP5/CR6 mainboard + 4c53 1020 VR6 mainboard + 4c53 1030 PC5 mainboard + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard 2001 79c978 [HomePNA] 1092 0a78 Multimedia Home Network Adapter 1668 0299 ActionLink Home Network Adapter + 2003 Am 1771 MBW [Alchemy] 2020 53c974 [PCscsi] 2040 79c974 3000 ELanSC520 Microcontroller @@ -817,6 +908,7 @@ 746b AMD-8111 ACPI 746d AMD-8111 AC97 Audio 746e AMD-8111 MC97 Modem + 756b AMD-8111 ACPI 1023 Trident Microsystems 0194 82C194 2000 4DWave DX @@ -939,13 +1031,15 @@ 1028 00d0 PowerEdge Expandable RAID Controller 3/Si 0005 PowerEdge Expandable RAID Controller 3/Di 0006 PowerEdge Expandable RAID Controller 3/Di - 0007 Remote Assistant Card 3 - 0008 PowerEdge Expandable RAID Controller 3/Di + 0007 Remote Access Controller:DRAC III + 0008 Remote Access Controller + 0009 BMC/SMIC device not present 000a PowerEdge Expandable RAID Controller 3 1028 0106 PowerEdge Expandable RAID Controller 3/Di 1028 011b PowerEdge Expandable RAID Controller 3/Di 1028 0121 PowerEdge Expandable RAID Controller 3/Di - 000c Embedded Systems Management Device 4 + 000c Remote Access Controller:ERA or ERA/O + 000d BMC/SMIC device 000e PowerEdge Expandable RAID Controller 000f PowerEdge Expandable RAID Controller 4/Di 1029 Siemens Nixdorf IS @@ -955,9 +1049,11 @@ 102b Matrox Graphics, Inc. # DJ: I've a suspicion that 0010 is a duplicate of 0d10. 0010 MGA-I [Impression?] + 0100 MGA 1064SG [Mystique] 0518 MGA-II [Athena] 0519 MGA 2064W [Millennium] 051a MGA 1064SG [Mystique] + 102b 0100 MGA-1064SG Mystique 102b 1100 MGA-1084SG Mystique 102b 1200 MGA-1084SG Mystique 1100 102b MGA-1084SG Mystique @@ -1081,6 +1177,12 @@ 00b8 F64310 00c0 F69000 HiQVideo 102c 00c0 F69000 HiQVideo + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1010 CP5/CR6 mainboard + 4c53 1020 VR6 mainboard + 4c53 1030 PC5 mainboard + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard 00d0 F65545 00d8 F65545 00dc F65548 @@ -1092,6 +1194,11 @@ 00f4 F68554 HiQVision 00f5 F68555 0c30 F69030 + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard +# C5C project cancelled + 4c53 1080 CT8 mainboard 102d Wyse Technology Inc. 50dc 3328 Audio 102e Olivetti Advanced Technology @@ -1107,6 +1214,7 @@ 6057 MiroVideo DC10/DC30+ 1032 Compaq 1033 NEC Corporation + 0000 Vr4181A USB Host or Function Control Unit 0001 PCI to 486-like bus Bridge 0002 PCI to VL98 Bridge 0003 ATM Controller @@ -1147,9 +1255,11 @@ 00a6 VRC5477 AC97 00cd IEEE 1394 [OrangeLink] Host Controller 12ee 8011 Root hub + 00df Vr4131 00e0 USB 2.0 12ee 7001 Root hub 1799 0002 Root Hub + 00f3 uPD6113x Multimedia Decoder/Processor [EMMA2] 1034 Framatome Connectors USA Inc. 1035 Comp. & Comm. Research Lab 1036 Future Domain Corp. @@ -1157,7 +1267,8 @@ 1037 Hitachi Micro Systems 1038 AMP, Inc 1039 Silicon Integrated Systems [SiS] - 0001 5591/5592 AGP +# This is what all my tests report. I don't know if this is equivalent to "5591/5592 AGP". + 0001 SiS 530 Virtual PCI-to-PCI bridge (AGP) 0002 SG86C202 0006 85C501/2/3 0008 85C503/5513 @@ -1167,8 +1278,12 @@ 1039 0000 SiS5597 SVGA (Shared RAM) 0204 82C204 0205 SG86C205 - 0300 300/200 + 0300 SiS300/305 PCI/AGP VGA Display Adapter 107d 2720 Leadtek WinFast VR300 + 0310 SiS315H PCI/AGP VGA Display Adapter + 0315 SiS315 PCI/AGP VGA Display Adapter + 0325 SiS315PRO PCI/AGP VGA Display Adapter + 0330 SiS330 [Xabre] PCI/AGP VGA Display Adapter 0406 85C501/2 0496 85C496 0530 530 Host @@ -1181,6 +1296,7 @@ 0635 635 Host 0645 SiS645 Host & Memory & AGP Controller 0646 SiS645DX Host & Memory & AGP Controller + 0648 SiS 645xx 0650 650 Host 0651 SiS651 Host 0730 730 Host @@ -1188,18 +1304,23 @@ 0735 735 Host 0740 740 Host 0745 745 Host + 0746 746 Host + 0755 SiS 755 Host Bridge 0900 SiS900 10/100 Ethernet 1039 0900 SiS900 10/100 Ethernet Adapter + 1043 8035 CUSI-FX motherboard 0961 SiS961 [MuTIOL Media IO] 0962 SiS962 [MuTIOL Media IO] 3602 83C602 5107 5107 5300 SiS540 PCI Display Adapter + 5315 SiS550 AGP/VGA VGA Display Adapter 5401 486 PCI Chipset 5511 5511/5512 5513 5513 [IDE] 1019 0970 P6STP-FL motherboard 1039 5513 SiS5513 EIDE Controller (A,B step) + 1043 8035 CUSI-FX motherboard 5517 5517 5571 5571 5581 5581 Pentium Chipset @@ -1213,8 +1334,10 @@ 6236 6236 3D-AGP 6300 SiS630 GUI Accelerator+3D 1019 0970 P6STP-FL motherboard + 1043 8035 CUSI-FX motherboard 6306 SiS530 3D PCI/AGP 1039 6306 SiS530,620 GUI Accelerator+3D + 6325 SiS650/651/M650/740 PCI/AGP VGA Display Adapter 6326 86C326 5598/6326 1039 6326 SiS6326 GUI Accelerator 1092 0a50 SpeedStar A50 @@ -1222,14 +1345,14 @@ 1092 4910 SpeedStar A70 1092 4920 SpeedStar A70 1569 6326 SiS6326 GUI Accelerator - 7001 7001 + 7001 USB 1.0 Controller 1039 7000 Onboard USB Controller - 7002 SiS7002 USB 2.0 + 7002 USB 2.0 Controller 1509 7002 Onboard USB Controller 7007 FireWire Controller - 7012 SiS7012 PCI Audio Accelerator - 7013 56k Winmodem (Smart Link HAMR5600 compatible) - 7016 SiS7016 10/100 Ethernet Adapter + 7012 Sound Controller + 7013 Intel 537 [56k Winmodem] + 7016 10/100 Ethernet Adapter 1039 7016 SiS7016 10/100 Ethernet Adapter 7018 SiS PCI Audio Accelerator 1014 01b6 SiS PCI Audio Accelerator @@ -1254,6 +1377,7 @@ 15c5 0111 SiS PCI Audio Accelerator 270f a171 SiS PCI Audio Accelerator a0a0 0022 SiS PCI Audio Accelerator + 7019 SiS7019 Audio Accelerator 103a Seiko Epson Corporation 103b Tatung Co. of America 103c Hewlett-Packard Company @@ -1286,7 +1410,6 @@ 103c 1226 Keystone SP2 103c 1227 Powerbar SP2 103c 1282 Everest SP2 - 1054 PCI Local Bus Adapter 1064 79C970 PCnet Ethernet Controller 108b Visualize FXe 10c1 NetServer Smart IRQ Router @@ -1298,7 +1421,7 @@ 121c NetServer PCI COM Port Decoder 1229 zx1 System Bus Adapter 122a zx1 I/O Controller - 122e PCI-X/AGP Local Bus Adapter + 122e zx1 Local Bus Adapter 1290 Auxiliary Diva Serial Port 2910 E2910A PCIBus Exerciser 2925 E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer @@ -1307,13 +1430,15 @@ 1040 Accelgraphics Inc. 1041 Computrend 1042 Micron - 1000 FDC 37C665 - 1001 37C922 + 1000 PC Tech RZ1000 + 1001 PC Tech RZ1001 3000 Samurai_0 3010 Samurai_1 3020 Samurai_IDE 1043 Asustek Computer, Inc. 0675 ISDNLink P-IN100-ST-D + 4021 v7100 Combo Deluxe [GeForce2 MX + TV tuner] + 4057 v8200 GeForce 3 1044 Distributed Processing Technology 1012 Domino RAID Engine a400 SmartCache/Raid I-IV Controller @@ -1375,7 +1500,7 @@ c832 82C832 c861 82C861 c895 82C895 - c935 EV1935 ECTIVA MachOne PCI Audio + c935 EV1935 ECTIVA MachOne PCIAudio d568 82C825 [Firebridge 2] d721 IDE [FireStar] 1046 IPC Corporation, Ltd. @@ -1385,14 +1510,24 @@ 1000 QuickStep 1000 3000 QuickStep 3000 1049 Fountain Technologies, Inc. -104a SGS Thomson Microelectronics +# # nee SGS Thomson Microelectronics +104a STMicroelectronics 0008 STG 2000X 0009 STG 1764X 0010 STG4000 [3D Prophet Kyro Series] + 0209 STPC Consumer/Industrial North- and Southbridge + 020a STPC Atlas/ConsumerS/Consumer IIA Northbridge +# From + 0210 STPC Atlas ISA Bridge + 021a STPC Consumer S Southbridge + 021b STPC Consumer IIA Southbridge + 0500 ST70137 [Unicorn] ADSL DMT Transceiver + 0564 STPC Client Northbridge 0981 DEC-Tulip compatible 10/100 Ethernet 1746 STG 1764X 2774 DEC-Tulip compatible 10/100 Ethernet 3520 MPEG-II decoder card + 55cc STPC Client Southbridge 104b BusLogic 0140 BT-946C (old) [multimaster 01] 1040 BT-946C (BA80C30) [MultiMaster 10] @@ -1401,6 +1536,7 @@ 0500 100 MBit LAN Controller 0508 TMS380C2X Compressor Interface 1000 Eagle i/f AS + 104c PCI1510 PC card Cardbus Controller 3d04 TVP4010 [Permedia] 3d07 TVP4020 [Permedia 2] 1011 4d10 Comet @@ -1444,7 +1580,11 @@ 8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) 8027 PCI4451 IEEE-1394 Controller 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100) - 8400 USR2210 22Mbps Wireless PC Card + 8029 PCI4510 IEEE-1394 Controller + 8400 ACX 100 22Mbps Wireless Interface + 8401 ACX 100 22Mbps Wireless Interface +# OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi + 9000 Wireless Interface (of unknown type) a001 TDC1570 a100 TDC1561 a102 TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f @@ -1460,7 +1600,9 @@ ac19 PCI1221 ac1a PCI1210 ac1b PCI1450 + 0e11 b113 Armada M700 ac1c PCI1225 + 0e11 b121 Armada E500 ac1d PCI1251A ac1e PCI1211 ac1f PCI1251B @@ -1474,15 +1616,18 @@ ac41 PCI4410 PC card Cardbus Controller ac42 PCI4451 PC card Cardbus Controller 1028 00e6 PCI4451 PC card CardBus Controller (Dell Inspiron 8100) + ac44 PCI4510 PC card Cardbus Controller ac50 PCI1410 PC card Cardbus Controller ac51 PCI1420 1014 023b ThinkPad T23 (2647-4MG) + 1028 00b1 Latitude C600 10cf 1095 Lifebook C6155 e4bf 1000 CP2-2-HIPHOP ac52 PCI1451 PC card Cardbus Controller ac53 PCI1421 PC card Cardbus Controller ac55 PCI1250 PC card Cardbus Controller 1014 0512 ThinkPad T30 + ac56 PCI1510 PC card Cardbus Controller ac60 PCI2040 PCI to DSP Bridge Controller fe00 FireWire Host Controller fe03 12C01A FireWire Host Controller @@ -1564,7 +1709,9 @@ 0d38 20263 105a 4d39 Fasttrak66 1275 20275 + 3318 PDC20318 (SATA150 TX4) 3376 PDC20376 + 1043 809e A7V8X motherboard 4d30 20267 105a 4d33 Ultra100 105a 4d39 Fasttrak100 @@ -1577,6 +1724,7 @@ 4d68 20268 105a 4d68 Ultra100TX2 4d69 20269 + 105a 4d68 Ultra133TX2 5275 PDC20276 IDE 105a 0275 SuperTrak SX6000 IDE 5300 DC5300 @@ -1584,6 +1732,7 @@ 6269 PDC20271 105a 6269 FastTrak TX2/TX2000 6621 PDC20621 [SX4000] 4 Channel IDE RAID Controller + 6629 PDC20619 FastTrak TX4000 RAID 7275 PDC20277 105b Foxconn International, Inc. 105c Wipro Infotech Limited @@ -1621,6 +1770,7 @@ 13cc 0009 Barco Metheus 5 Megapixel, Dual Head 13cc 000a Barco Metheus 5 Megapixel, Dual Head 5348 Revolution 4 + 105d 0037 Revolution IV-FP AGP (For SGI 1600SW) 105e Vtech Computers Ltd 105f Infotronic America Inc 1060 United Microelectronics [UMC] @@ -1669,6 +1819,7 @@ 0002 DAC960PD 0010 DAC960PX 0050 AcceleRAID 352/170/160 support Device + b166 Gemstone chipset SCSI controller ba55 eXtremeRAID 1100 support Device ba56 eXtremeRAID 2000/3000 support Device 106a Aten Research Inc @@ -1759,6 +1910,7 @@ 2100 QLA2100 64-bit Fibre Channel Adapter 1077 0001 QLA2100 64-bit Fibre Channel Adapter 2200 QLA2200 + 1077 0002 QLA2200 2300 QLA2300 64-bit FC-AL Adapter 2312 QLA2312 Fibre Channel Adapter 1078 Cyrix Corporation @@ -1856,7 +2008,6 @@ 8001 Schizo PCI Bus Module a000 Ultra IIi a001 Ultra IIe - a801 Tomatillo PCI Bus Module 108f Systemsoft 1090 Encore Computer Corporation 1091 Intergraph Corporation @@ -1896,6 +2047,8 @@ 1190 PCI-MIO-16E-4 1330 PCI-6031E 1350 PCI-6071E + 17d0 PCI-6503 + 2410 PCI-6733 2a60 PCI-6023E b001 IMAQ-PCI-1408 b011 IMAQ-PXI-1408 @@ -1911,6 +2064,7 @@ c831 PCI-GPIB bridge 1094 First International Computers [FIC] 1095 CMD Technology Inc + 0240 Adaptec AAR-1210SA SATA HostRAID Controller 0640 PCI0640 0643 PCI0643 0646 PCI0646 @@ -1925,6 +2079,7 @@ 1095 0670 USB0670 0673 USB0673 0680 PCI0680 + 3112 Silicon Image SiI 3112 SATARaid Controller 1096 Alacron 1097 Appian Technology 1098 Quantum Designs (H.K.) Ltd @@ -1944,8 +2099,10 @@ 036c Bt879(??) Video Capture 13e9 0070 Win/TV (Video Section) 036e Bt878 Video Capture - 0070 13eb WinTV/GO + 0070 13eb WinTV Series 0070 ff01 Viewcast Osprey 200 + 107d 6606 WinFast TV 2000 + 11bd 0012 PCTV pro (TV + FM stereo receiver) 11bd 001c PCTV Sat (DBC receiver) 127a 0001 Bt878 Mediastream Controller NTSC 127a 0002 Bt878 Mediastream Controller PAL BG @@ -1996,10 +2153,11 @@ 1851 1851 FlyVideo'98 EZ - video 1852 1852 FlyVideo'98 (with FM Tuner) 0878 Bt878 Audio Capture - 0070 13eb WinTV/GO + 0070 13eb WinTV Series 0070 ff01 Viewcast Osprey 200 1002 0001 TV-Wonder 1002 0003 TV-Wonder/VE + 11bd 0012 PCTV pro (TV + FM stereo receiver, audio section) 11bd 001c PCTV Sat (DBC receiver) 127a 0001 Bt878 Video Capture (Audio Section) 127a 0002 Bt878 Video Capture (Audio Section) @@ -2055,6 +2213,7 @@ 10a3 Everex Systems Inc 10a4 Globe Manufacturing Sales 10a5 Smart Link Ltd. + 3052 SmartPCI562 56K Modem 5449 SmartPCI561 modem 10a6 Informtech Industrial Ltd. 10a7 Benchmarq Microelectronics @@ -2070,6 +2229,7 @@ 0007 RPCEX 0008 DiVO VIP 0009 Alteon Gigabit Ethernet + 10a9 8002 Acenic Gigabit Ethernet 0010 AMP Video I/O 0011 GRIP 0012 SGH PSHAC GSN @@ -2081,6 +2241,7 @@ 1006 Dual JPEG 4 1007 Dual JPEG 5 1008 Cesium + 100a IOC4 I/O controller 2001 Fibre Channel 2002 ASDE 8001 O2 1394 @@ -2134,6 +2295,7 @@ 15ed 1001 Macrolink MCCS 16-port Serial 15ed 1002 Macrolink MCCS 8-port Serial Hot Swap 15ed 1003 Macrolink MCCS 16-port Serial Hot Swap + 5654 5634 OpenLine4 Telephony Card d531 c002 PCIntelliCAN 2xSJA1000 CAN bus d84d 4006 EX-4006 1P d84d 4008 EX-4008 1P EPP/ECP @@ -2154,6 +2316,8 @@ d84d 4078 EX-4078 2S(16C552) RS-232+1P 9054 PCI <-> IOBus Bridge 10b5 2455 Wessex Techology PHIL-PCI + 10b5 2696 Innes Corp AM Radcap card + 12d9 0002 PCI Prosody Card rev 1.5 9060 9060 906d 9060SD 125c 0640 Aries 16000P @@ -2161,6 +2325,8 @@ 9080 9080 10b5 9080 9080 [real subsystem ID not set] 129d 0002 Aculab PCI Prosidy card + 12d9 0002 PCI Prosody Card + bb04 B&B 3PCIOSD1A Isolated PCI Serial 10b6 Madge Networks 0001 Smart 16/4 PCI Ringnode 0002 Smart 16/4 PCI Ringnode Mk2 @@ -2188,12 +2354,11 @@ 1001 Collage 155 ATM Server Adapter 10b7 3Com Corporation 0001 3c985 1000BaseSX (SX/TX) + 0910 3C910-A01 1006 MINI PCI type 3B Data Fax Modem 1007 Mini PCI 56k Winmodem 10b7 615c Mini PCI 56K Modem - 1700 Gigabit Ethernet Adapter - 10b7 0010 3Com 3C940 Gigabit LOM Ethernet Adapter - 10b7 0020 3Com 3C941 Gigabit LOM Ethernet Adapter + 1700 3c940 1000Base? 3390 3c339 TokenLink Velocity 3590 3c359 TokenLink Velocity XL 10b7 3590 TokenLink Velocity XL Adapter (3C359/359B) @@ -2226,6 +2391,7 @@ 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus 6564 3CCFEM656 [id 6564] Cyclone CardBus 7646 3cSOHO100-TX Hurricane + 7770 3CRWE777 PCI(PLX) Wireless Adaptor [Airconnect] 7940 3c803 FDDILink UTP Controller 7980 3c804 FDDILink SAS Controller 7990 3c805 FDDILink DAS Controller @@ -2266,10 +2432,11 @@ 9058 3c905B-Combo [Deluxe Etherlink XL 10/100] 905a 3c905B-FX [Fast Etherlink XL FX 10/100] 9200 3c905C-TX/TX-M [Tornado] - 1028 0095 Integrated 3C905C-TX Fast Etherlink for PC Management NIC + 1028 0095 3C920 Integrated Fast Ethernet Controller + 1028 0097 3C920 Integrated Fast Ethernet Controller 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC 10b7 7000 10/100 Mini PCI Ethernet Adapter - 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller + 9201 3C920B-EMB Integrated Fast Ethernet Controller 9300 3CSOHO100B-TX [910-A01] 9800 3c980-TX [Fast Etherlink XL Server Adapter] 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter @@ -2277,6 +2444,7 @@ 10b7 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra] 10b7 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra] 10b7 9805 3c980 10/100baseTX NIC [Python-T] + 10f1 2462 Thunder K7 S2462 9900 3C990-TX [Typhoon] 9902 3CR990-TX-95 [Typhoon 56-bit] 9903 3CR990-TX-97 [Typhoon 168-bit] @@ -2370,12 +2538,16 @@ 5251 M5251 P1394 OHCI 1.0 Controller 5253 M5253 P1394 OHCI 1.1 Controller 5261 M5261 Ethernet Controller + 5450 Lucent Technologies Soft Modem AMR 5451 M5451 PCI AC-Link Controller Audio Device 1014 0506 ThinkPad R30 5453 M5453 PCI AC-Link Controller Modem Device 5455 M5455 PCI AC-Link Controller Audio Device - 5457 M5457 AC-Link Modem Interface Controller - 5459 SmartPCI561 56K Modem + 5457 Intel 537 [M5457 AC-Link Modem] +# Same but more usefull for driver's lookup + 5459 SmartLink SmartPCI561 56K Modem +# SmartLink PCI SoftModem + 545a SmartLink SmartPCI563 56K Modem 5471 M5471 Memory Stick Controller 5473 M5473 SD-MMC Controller 7101 M7101 PMU @@ -2444,7 +2616,10 @@ 10c9 Dataexpert Corporation 10ca Fujitsu Microelectr., Inc. 10cb Omron Corporation -10cc Mentor ARC Inc +# nee Mentor ARC Inc +10cc Mai Logic Incorporated + 0660 Articia S Host Bridge + 0661 Articia S PCI Bridge 10cd Advanced System Products, Inc 1100 ASC1100 1200 ASC1200 [(abp940) Fast SCSI-II] @@ -2453,9 +2628,9 @@ 2300 ABP940-UW 2500 ABP940-U2W 10ce Radius -10cf Citicorp TTI +# nee Citicorp TTI +10cf Fujitsu Limited. 2001 mb86605 -10d0 Fujitsu Limited 10d1 FuturePlus Systems Corp. 10d2 Molex Incorporated 10d3 Jabil Circuit Inc @@ -2485,7 +2660,7 @@ 0008 NV1 [EDGE 3D] 0009 NV1 [EDGE 3D] 0010 NV2 [Mutara V08] - 0020 NV4 [Riva TnT] + 0020 NV4 [RIVA TNT] 1043 0200 V3400 TNT 1048 0c18 Erazor II SGRAM 1048 0c1b Erazor II @@ -2507,11 +2682,12 @@ 10de 0020 Riva TNT 1102 1015 Graphics Blaster CT6710 1102 1016 Graphics Blaster RIVA TNT - 0028 NV5 [Riva TnT2] + 0028 NV5 [RIVA TNT2/TNT2 Pro] 1043 0200 AGP-V3800 SGRAM 1043 0201 AGP-V3800 SDRAM 1043 0205 PCI-V3800 1043 4000 AGP-V3800PRO + 1048 0c21 Synergy II 1092 4804 Viper V770 1092 4a00 Viper V770 1092 4a02 Viper V770 Ultra @@ -2523,7 +2699,7 @@ 1102 1020 3D Blaster RIVA TNT2 1102 1026 3D Blaster RIVA TNT2 Digital 14af 5810 Maxi Gamer Xentor - 0029 NV5 [Riva TnT2 Ultra] + 0029 NV5 [RIVA TNT2 Ultra] 1043 0200 AGP-V3800 Deluxe 1043 0201 AGP-V3800 Ultra SDRAM 1043 0205 PCI-V3800 Ultra @@ -2533,17 +2709,18 @@ 14af 5820 Maxi Gamer Xentor 32 002a NV5 [Riva TnT2] 002b NV5 [Riva TnT2] - 002c NV6 [Vanta] + 002c NV6 [Vanta/Vanta LT] 1043 0200 AGP-V3800 Combat SDRAM 1043 0201 AGP-V3800 Combat 1092 6820 Viper V730 1102 1031 CT6938 VANTA 8MB 1102 1034 CT6894 VANTA 16MB 14af 5008 Maxi Gamer Phoenix 2 - 002d RIVA TNT2 Model 64 + 002d NV5M64 [RIVA TNT2 Model 64/Model 64 Pro] 1043 0200 AGP-V3800M 1043 0201 AGP-V3800M 1048 0c3a Erazor III LT + 10de 001e M64 AGP4x 1102 1023 CT6892 RIVA TNT2 Value 1102 1024 CT6932 RIVA TNT2 Value 32Mb 1102 102c CT6931 RIVA TNT2 Value [Jumper] @@ -2551,8 +2728,32 @@ 1554 1041 PixelView RIVA TNT2 M64 32MB 002e NV6 [Vanta] 002f NV6 [Vanta] - 00a0 NV5 [Riva TNT2] + 0060 nForce2 ISA Bridge + 1043 80ad A7N8X Mainboard + 0064 nForce2 SMBus (MCP) + 0065 nForce2 IDE + 0066 nForce2 Ethernet Controller + 0067 nForce2 USB Controller + 1043 0c11 A7N8X Mainboard + 0068 nForce2 USB Controller + 1043 0c11 A7N8X Mainboard + 006a nForce2 AC97 Audio Controler (MCP) + 006b nForce MultiMedia audio [Via VT82C686B] + 006c nForce2 External PCI Bridge + 006d nForce2 PCI Bridge + 006e nForce2 FireWire (IEEE 1394) Controller + 00a0 NV5 [Aladdin TNT2] 14af 5810 Maxi Gamer Xentor + 00d0 nForce3 LPC Bridge + 00d1 nForce3 Host Bridge + 00d2 nForce3 AGP Bridge + 00d4 nForce3 SMBus + 00d5 nForce3 IDE + 00d6 nForce3 Ethernet + 00d7 nForce3 USB 1.1 + 00d8 nForce3 USB 2.0 + 00da nForce3 Audio + 00dd nForce3 PCI Bridge 0100 NV10 [GeForce 256 SDR] 1043 0200 AGP-V6600 SGRAM 1043 0201 AGP-V6600 SDRAM @@ -2560,45 +2761,57 @@ 1043 4009 AGP-V6600 SDRAM 1102 102d CT6941 GeForce 256 14af 5022 3D Prophet SE - 0101 NV10 [GeForce 256 DDR] + 0101 NV10DDR [GeForce 256 DDR] 1043 0202 AGP-V6800 DDR 1043 400a AGP-V6800 DDR SGRAM 1043 400b AGP-V6800 DDR SDRAM + 107d 2822 WinFast GeForce 256 1102 102e CT6971 GeForce 256 DDR 14af 5021 3D Prophet DDR-DVI - 0103 NV10 [Quadro] - 0110 NV11 [GeForce2 MX] + 0103 NV10GL [Quadro] + 0110 NV11 [GeForce2 MX/MX 400] 1043 4015 AGP-V7100 Pro 1043 4031 V7100 Pro with TV output + 1462 8817 MSI GeForce2 MX400 Pro32S [MS-8817] 14af 7102 3D Prophet II MX 14af 7103 3D Prophet II MX Dual-Display - 0111 NV11 [GeForce2 MX DDR] + 0111 NV11DDR [GeForce2 MX 100 DDR/200 DDR] 0112 NV11 [GeForce2 Go] - 0113 NV11 [GeForce2 MXR] - 0150 NV15 [GeForce2 GTS] + 0113 NV11GL [Quadro2 MXR/EX] + 0150 NV15 [GeForce2 GTS/Pro] 1043 4016 V7700 AGP Video Card 107d 2840 WinFast GeForce2 GTS with TV output 1462 8831 Creative GeForce2 Pro - 0151 NV15 [GeForce2 Ti] + 0151 NV15DDR [GeForce2 Ti] 1043 405f V7700Ti - 0152 NV15 [GeForce2 Ultra, Bladerunner] + 0152 NV15BR [GeForce2 Ultra, Bladerunner] 1048 0c56 GLADIAC Ultra - 0153 NV15 [Quadro2 Pro] - 0170 NV17 [GeForce4 MX460] - 0171 NV17 [GeForce4 MX440] + 0153 NV15GL [Quadro2 Pro] + 0170 NV17 [GeForce4 MX 460] + 0171 NV17 [GeForce4 MX 440] + 10b0 0002 Gainward Pro/600 TV 1462 8661 G4MX440-VTP - 0172 NV17 [GeForce4 MX420] - 0173 NV1x + 1462 8730 MX440SES-T (MS-8873) + 147b 8f00 Abit Siluro GeForce4MX440 + 0172 NV17 [GeForce4 MX 420] + 0173 NV17 [GeForce4 MX 440-SE] 0174 NV17 [GeForce4 440 Go] 0175 NV17 [GeForce4 420 Go] 0176 NV17 [GeForce4 420 Go 32M] - 0178 Quadro4 500XGL + 0178 NV17GL [Quadro4 550 XGL] 0179 NV17 [GeForce4 440 Go 64M] - 017a Quadro4 200/400NVS - 017b Quadro4 550XGL - 017c Quadro4 550 GoGL - 0181 NV18 [GeForce4 MX440 AGP 8x] - 01a0 NV15 [GeForce2 - nForce GPU] + 017a NV17GL [Quadro4 200/400 NVS] + 017b NV17GL [Quadro4 550 XGL] + 017c NV17GL [Quadro4 550 GoGL] + 0181 NV18 [GeForce4 MX 440 AGP 8x] + 1043 806f V9180 Magic + 1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X + 0182 NV18 [GeForce4 MX 440SE AGP 8x] + 0183 NV18 [GeForce4 MX 420 AGP 8x] + 0188 NV18GL [Quadro4 580 XGL] + 018a NV18GL [Quadro4 NVS AGP 8x] + 018b NV18GL [Quadro4 380 XGL] + 01a0 NVCrush11 [GeForce2 MX Integrated Graphics] 01a4 nForce CPU bridge 01ab nForce 420 Memory Controller (DDR) 01ac nForce 220/420 Memory Controller @@ -2609,24 +2822,53 @@ 01b7 nForce AGP to PCI Bridge 01b8 nForce PCI-to-PCI bridge 01bc nForce IDE - 01c1 nForce MC97 Modem (Smart Link HAMR5600 compatible) + 01c1 Intel 537 [nForce MC97 Modem] 01c2 nForce USB Controller 01c3 nForce Ethernet Controller + 01e0 nForce2 AGP (different version?) + 01e8 nForce2 AGP + 01ea nForce2 Memory Controller 0 + 01eb nForce2 Memory Controller 1 + 01ec nForce2 Memory Controller 2 + 01ed nForce2 Memory Controller 3 + 01ee nForce2 Memory Controller 4 + 01ef nForce2 Memory Controller 5 + 01f0 NV18 [GeForce4 MX - nForce GPU] 0200 NV20 [GeForce3] 1043 402f AGP-V8200 DDR - 0201 NV20 [GeForce3 Ti200] - 0202 NV20 [GeForce3 Ti500] + 0201 NV20 [GeForce3 Ti 200] + 0202 NV20 [GeForce3 Ti 500] 1043 405b V8200 T5 1545 002f Xtasy 6964 - 0203 NV20 [Quadro DCC] - 0250 NV25 [GeForce4 Ti4600] - 0251 NV25 [GeForce4 Ti4400] - 0253 NV25 [GeForce4 Ti4200] + 0203 NV20DCC [Quadro DCC] + 0250 NV25 [GeForce4 Ti 4600] + 0251 NV25 [GeForce4 Ti 4400] + 0252 NV25 [GeForce4 Ti] + 0253 NV25 [GeForce4 Ti 4200] 107d 2896 WinFast A250 LE TD (Dual VGA/TV-out/DVI) 147b 8f09 Siluro (Dual VGA/TV-out/DVI) - 0258 Quadro4 900XGL - 0259 Quadro4 750XGL - 025b Quadro4 700XGL + 0258 NV25GL [Quadro4 900 XGL] + 0259 NV25GL [Quadro4 750 XGL] + 025b NV25GL [Quadro4 700 XGL] + 0280 NV28 [GeForce4 Ti 4800] + 0281 NV28 [GeForce4 Ti 4200 AGP 8x] + 0282 NV28 [GeForce4 Ti 4800 SE] + 0286 NV28 [GeForce4 Ti 4200 Go AGP 8x] + 0288 NV28GL [Quadro4 980 XGL] + 0289 NV28GL [Quadro4 780 XGL] + 0300 NV30 [GeForce FX] + 0301 NV30 [GeForce FX 5800 Ultra] + 0302 NV30 [GeForce FX 5800] + 0308 NV30GL [Quadro FX 2000] + 0309 NV30GL [Quadro FX 1000] + 0311 NV31 [GeForce FX 5600 Ultra] + 0312 NV31 [GeForce FX 5600] + 0321 NV34 [GeForce FX 5200 Ultra] + 0322 NV34 [GeForce FX 5200] + 032b NV34GL [Quadro FX 500] + 0330 NV35 [GeForce FX 5900 Ultra] + 0331 NV35 [GeForce FX 5900] + 0338 NV35GL [Quadro FX 3000] 10df Emulex Corporation 1ae5 LP6000 Fibre Channel Host Adapter f085 LP850 Fibre Channel Adapter @@ -2652,6 +2894,7 @@ 10e3 Tundra Semiconductor Corp. 0000 CA91C042 [Universe] 0860 CA91C860 [QSpan] + 0862 CA91C862A [QSpan-II] 10e4 Tandem Computers 10e5 Micro Industries Corporation 10e6 Gainbery Computer Products Inc. @@ -2672,6 +2915,7 @@ 811a PCI-IEEE1355-DS-DE Interface 8170 S5933 [Matchmaker] (Chipset Development Tool) 82db AJA HDNTV HD SDI Framestore + 8851 S5933 on Innes Corp FM Radio Capture card 10e9 Alps Electric Co., Ltd. 10ea Intergraphics Systems 1680 IGA-1680 @@ -2681,6 +2925,7 @@ 2010 CyberPro 2000A 5000 CyberPro 5000 5050 CyberPro 5050 + 5202 CyberPro 5202 10eb Artists Graphics 0101 3GA 8111 Twist3 Frame Grabber @@ -2719,6 +2964,7 @@ 8e2e 7100 KF-230TX/2 a0a0 0007 ALN-325C 8169 RTL-8169 + 1371 434e ProG-2000L 8197 SmartLAN56 56K Modem 10ed Ascii Corporation 7310 V7310 @@ -2729,6 +2975,7 @@ 3fc3 RME Digi96/8 Pad 3fc4 RME Digi9652 (Hammerfall) 3fc5 RME Hammerfall DSP + 8381 Ellips Santos Frame Grabber 10ef Racore Computer Products, Inc. 8154 M815x Token Ring Adapter 10f0 Peritek Corporation @@ -2777,6 +3024,8 @@ 1102 8040 CT4760 SBLive! 1102 8051 CT4850 SBLive! Value 1102 8061 SBLive! Player 5.1 + 1102 8064 SB Live! 5.1 Model SB0100 + 1102 8065 SBLive! 5.1 Digital Model SB0220 0004 SB Audigy 1102 0051 SB0090 Audigy Player 1102 0053 SB0090 Audigy Player/OEM @@ -2788,7 +3037,8 @@ 7003 SB Audigy MIDI/Game port 1102 0040 SB Audigy MIDI/Game Port 7004 [SB Live! Value] Input device controller - 8938 ES1371 + 8064 SB0100 [SBLive! 5.1 OEM] + 8938 Ectiva EV1938 1103 Triones Technologies, Inc. 0003 HPT343 # Revisions: 01=HPT366, 03=HPT370, 04=HPT370A, 05=HPT372 @@ -2799,6 +3049,7 @@ 0006 HPT302 0007 HPT371 0008 HPT374 + 0009 HPT372N 1104 RasterOps Corp. 1105 Sigma Designs, Inc. 1105 REALmagic Xcard MPEG 1/2/3/4 DVD Decoder @@ -2809,15 +3060,21 @@ 0130 VT6305 1394.A Controller 0305 VT8363/8365 [KT133/KM133] 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard 1043 8042 A7V133/A7V133-C Mainboard 147b a401 KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard 0391 VT8371 [KX133] 0501 VT8501 [Apollo MVP4] 0505 VT82C505 - 0561 VT82C561 - 0571 VT82C586/B/686A/B PIPC Bus Master IDE +# Shares chip with :0576. The VT82C576M has :1571 instead of :0561. + 0561 VT82C576MV + 0571 VT82C586A/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE + 1019 0985 P6VXA Motherboard 1043 8052 VT8233A Bus Master ATA100/66/33 IDE - 1106 0571 VT8235 Bus Master ATA133/100/66/33 IDE + 1043 808c A7V8X motherboard + 1106 0571 VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE + 1179 0001 Magnia Z310 + 1297 f641 FX41 motherboard 1458 5002 GA-7VAX Mainboard 0576 VT82C576 3V [Apollo Master] 0585 VT82C585VP [Apollo VP1/VPX] @@ -2831,24 +3088,36 @@ 0598 VT82C598 [Apollo MVP3] 0601 VT8601 [Apollo ProMedia] 0605 VT8605 [ProSavage PM133] + 1043 802c CUV4X mainboard 0680 VT82C680 [Apollo P6] 0686 VT82C686 [Apollo Super South] + 1019 0985 P6VXA Motherboard + 1043 802c CUV4X mainboard 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard 1043 8040 A7M266 Mainboard 1043 8042 A7V133/A7V133-C Mainboard 1106 0000 VT82C686/A PCI to ISA Bridge 1106 0686 VT82C686/A PCI to ISA Bridge + 1179 0001 Magnia Z310 + 147b a702 KG7-Lite Mainboard 0691 VT82C693A/694x [Apollo PRO133x] + 1019 0985 P6VXA Motherboard + 1179 0001 Magnia Z310 1458 0691 VT82C691 Apollo Pro System Controller 0693 VT82C693 [Apollo Pro Plus] 0698 VT82C693A [Apollo Pro133 AGP] 0926 VT82C926 [Amazon] 1000 VT82C570MV 1106 VT82C570MV - 1571 VT82C416MV + 1571 VT82C576M/VT82C586 1595 VT82C595/97 [Apollo VP2/97] 3038 USB - 0925 1234 MVP3 USB Controller + 0925 1234 USB Controller + 1019 0985 P6VXA Motherboard + 1043 808c A7V8X motherboard + 1179 0001 Magnia Z310 + 1458 5004 GA-7VAX Mainboard 3040 VT82C586B ACPI 3043 VT86C100A [Rhine] 10bd 0000 VT86C100A Fast Ethernet Adapter @@ -2858,22 +3127,29 @@ 3050 VT82C596 Power Management 3051 VT82C596 Power Management 3057 VT82C686 [Apollo Super ACPI] + 1019 0985 P6VXA Motherboard 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard 1043 8040 A7M266 Mainboard 1043 8042 A7V133/A7V133-C Mainboard + 1179 0001 Magnia Z310 3058 VT82C686 AC97 Audio Controller 0e11 b194 Soundmax integrated digital audio + 1019 0985 P6VXA Motherboard 1106 4511 Onboard Audio on EP7KXA 1458 7600 Onboard Audio 1462 3091 MS-6309 Onboard Audio 15dd 7609 Onboard Audio - 3059 VT8233 AC97 Audio Controller + 3059 VT8233/A/8235 AC97 Audio Controller + 1043 8095 A7V8X Motherboard (Realtek ALC650 codec) + 1297 c160 FX41 motherboard (Realtek ALC650 codec) 1458 a002 GA-7VAX Onboard Audio (Realtek ALC650) 3065 VT6102 [Rhine-II] 1106 0102 VT6102 [Rhine II] Embeded Ethernet Controller on VT8235 1186 1400 DFE-530TX rev A 1186 1401 DFE-530TX rev B - 3068 AC97 Modem Controller + 13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B) + 3068 Intel 537 [AC97 Modem] 3074 VT8233 PCI to ISA Bridge 1043 8052 VT8233A 3091 VT8633 [Apollo Pro266] @@ -2884,11 +3160,18 @@ 3102 VT8662 Host Bridge 3103 VT8615 Host Bridge 3104 USB 2.0 + 1043 808c A7V8X motherboard + 1297 f641 FX41 motherboard 1458 5004 GA-7VAX Mainboard 3106 VT6105 [Rhine-III] 3109 VT8233C PCI to ISA Bridge 3112 VT8361 [KLE133] Host Bridge - 3116 VT8375 [KM266] Host Bridge + 3116 VT8375 [KM266/KL266] Host Bridge + 1297 f641 FX41 motherboard +# found on EPIA M6000/9000 mainboard + 3122 VT8623 [Apollo CLE266] integrated CastleRock graphics +# found on EPIA M6000/9000 mainboard + 3123 VT8623 [Apollo CLE266] 3128 VT8753 [P4X266 AGP] 3133 VT3133 Host Bridge 3147 VT8233A ISA Bridge @@ -2896,8 +3179,11 @@ 3156 P/KN266 Host Bridge 3168 VT8374 P4X400 Host Controller/AGP Bridge 3177 VT8235 ISA Bridge + 1043 808c A7V8X motherboard + 1297 f641 FX41 motherboard 1458 5001 GA-7VAX Mainboard 3189 VT8377 [KT400 AGP] Host Bridge + 1043 807f A7V8X motherboard 1458 5000 GA-7VAX Mainboard 5030 VT82C596 ACPI [Apollo PRO] 6100 VT85C100A [Rhine II] @@ -2909,6 +3195,7 @@ 8596 VT82C596 [Apollo PRO AGP] 8597 VT82C597 [Apollo VP3 AGP] 8598 VT82C598/694x [Apollo MVP3/Pro133x AGP] + 1019 0985 P6VXA Motherboard 8601 VT8601 [Apollo ProMedia AGP] 8605 VT8605 [PM133 AGP] 8691 VT82C691 [Apollo Pro] @@ -2920,6 +3207,7 @@ b103 VT8615 AGP Bridge b112 VT8361 [KLE133] AGP Bridge b168 VT8235 PCI Bridge + b198 VT8237 PCI Bridge 1107 Stratus Computers 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!) 1108 Proteon, Inc. @@ -2936,7 +3224,14 @@ 110a Siemens Nixdorf AG 0002 Pirahna 2-port 0005 Tulip controller, power management, switch extender + 0006 FSC PINC (I/O-APIC) + 0015 FSC Multiprocessor Interrupt Controller + 001d FSC Copernicus Management Controller + 007b FSC Remote Service Controller, mailbox device + 007c FSC Remote Service Controller, shared memory device + 007d FSC Remote Service Controller, SMIC device 2102 DSCC4 WAN adapter + 4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter) 4942 FPGA I-Bus Tracer for MBD 6120 SZB6120 110b Chromatic Research Inc. @@ -3102,10 +3397,16 @@ 0001 MVC IM-PCI Video frame grabber/processor 1130 Computervision 1131 Philips Semiconductors + 1561 USB 1.1 Host Controller + 1562 USB 2.0 Host Controller 3400 SmartPCI56(UCB1500) 56K Modem 7130 SAA7130 Video Broadcast Decoder + 5168 0138 LiveView FlyVideo 2000 + 7133 SAA7133 Audio+video broadcast decoder + 5168 0138 LifeView FlyVideo 3000 # PCI audio and video broadcast decoder (http://www.semiconductors.philips.com/pip/saa7134hl) 7134 SAA7134 + 7135 SAA7135 Audio+video broadcast decoder 7145 SAA7145 7146 SAA7146 114b 2003 DVRaptor Video Edit/Capture Card @@ -3124,24 +3425,59 @@ b921 EiconCard P92 b922 EiconCard P92 b923 EiconCard P92 - e001 DIVA 20PRO - 1133 e001 DIVA Pro 2.0 S/T - e002 DIVA 20 - 1133 e002 DIVA 2.0 S/T - e003 DIVA 20PRO_U - 1133 e003 DIVA Pro 2.0 U - e004 DIVA 20_U - 1133 e004 DIVA 2.0 U - e005 DIVA LOW - 1133 e005 DIVA 2.01 S/T - e00b Eicon Diva 2.02 - e010 DIVA Server BRI-2M - 1133 e010 DIVA Server BRI-2M - e012 DIVA Server BRI-8M - 1133 e012 DIVA Server BRI-8M - e014 DIVA Server PRI-30M - 1133 e014 DIVA Server PRI-30M - e018 DIVA Server BRI-2M/-2F + e001 Diva Pro 2.0 S/T + e002 Diva 2.0 S/T PCI + e003 Diva Pro 2.0 U + e004 Diva 2.0 U PCI + e005 Diva 2.01 S/T PCI + e006 Diva CT S/T PCI + e007 Diva CT U PCI + e008 Diva CT Lite S/T PCI + e009 Diva CT Lite U PCI + e00a Diva ISDN+V.90 PCI + e00b Diva 2.02 PCI S/T + e00c Diva 2.02 PCI U + e00d Diva ISDN Pro 3.0 PCI + e00e Diva ISDN+CT S/T PCI Rev 2 + e010 Diva Server BRI-2M PCI + 110a 0021 Fujitsu Siemens ISDN S0 + 8001 0014 Diva Server BRI-2M PCI Cornet NQ + e011 Diva Server BRI S/T Rev 2 + e012 Diva Server 4BRI-8M PCI + 8001 0014 Diva Server 4BRI-8M PCI Cornet NQ + e013 Diva Server 4BRI-8M Rev 2 + 8001 0014 Diva Server 4BRI-8M Cornet NQ 2 + e014 Diva Server PRI-30M PCI + 0008 0100 Diva Server PRI-30M PCI + 8001 0014 Diva Server PRI-30M PCI Cornet NQ + e015 DIVA Server PRI-30M 2.0 + 8001 0014 Diva Server PRI Cornet NQ 2 + e016 Diva Server Voice 4BRI PCI + 8001 0014 Diva Server PRI Cornet NQ + e017 Diva Server Voice 4BRI PCI Rev 2 + 8001 0014 Diva Server Voice 4BRI PCI Cornet NQ 2 + e018 Diva Server BRI 2M Revision 2 + 8001 0014 Diva Server BRI 2M Cornet NQ 2 + e019 Diva Server Voice PRI PCI Rev 2 + 8001 0014 Diva Server Voice PRI PCI Cornet NQ 2 + e01a Diva Server 2FX + e01b Diva Server BRI-2M Voice Revision 2 + 8001 0014 Diva Server BRI-2M Voice Cornet NQ 2 + e01c Diva Server PRI Rev 3.0 + 1133 1c01 Diva Server PRI/E1/T1-8 Rev 3.0 + 1133 1c02 Diva Server PRI/T1-24 Rev 3.0 + 1133 1c03 Diva Server PRI/E1-30 Rev 3.0 + 1133 1c04 Diva Server V-PRI/E1/T1 Rev 3.0 + 1133 1c05 Diva Server V-PRI/T1-24 Rev 3.0 + 1133 1c06 Diva Server V-PRI/E1-30 Rev 3.0 + 1133 1c07 Diva Server PRI/E1/T1-8 Cornet NQ 3 + 1133 1c08 Diva Server PRI/T1-24 Cornet NQ 3 + 1133 1c09 Diva Server PRI/E1-30 Cornet NQ 3 + 1133 1c0a Diva Server V-PRI/E1/T1 Cornet NQ 3 + 1133 1c0b Diva Server V-PRI/T1-24 Cornet NQ 3 + 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ 3 + e01e Diva Server 2PRI + e020 Diva Server 4PRI 1134 Mercury Computer Systems 0001 Raceway Bridge 1135 Fuji Xerox Co Ltd @@ -3209,37 +3545,24 @@ 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64) 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS) 4200 Token Ring adapter - 4300 SK-98xx Gigabit Ethernet Server Adapter - 1148 9821 SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - 1148 9822 SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - 1148 9841 SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - 1148 9842 SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - 1148 9843 SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - 1148 9844 SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - 1148 9861 SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - 1148 9862 SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - 1148 9871 SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - 1148 9872 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - 1259 2970 Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - 1259 2971 Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - 1259 2972 Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - 1259 2973 Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - 1259 2974 Allied Telesyn AT-2971T Gigabit Ethernet Adapter - 1259 2975 Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - 1259 2976 Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - 1259 2977 Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - 4320 SK-98xx V2.0 Gigabit Ethernet Adapter - 1148 0121 Marvell RDK-8001 Adapter - 1148 0221 Marvell RDK-8002 Adapter - 1148 0321 Marvell RDK-8003 Adapter - 1148 0421 Marvell RDK-8004 Adapter - 1148 0621 Marvell RDK-8006 Adapter - 1148 0721 Marvell RDK-8007 Adapter - 1148 0821 Marvell RDK-8008 Adapter - 1148 0921 Marvell RDK-8009 Adapter - 1148 1121 Marvell RDK-8011 Adapter - 1148 1221 Marvell RDK-8012 Adapter - 1148 3221 SK-9521 V2.0 10/100/1000Base-T Adapter + 4300 Gigabit Ethernet + 1148 9821 SK-9821 (1000Base-T single link) + 1148 9822 SK-9822 (1000Base-T dual link) + 1148 9841 SK-9841 (1000Base-LX single link) + 1148 9842 SK-9842 (1000Base-LX dual link) + 1148 9843 SK-9843 (1000Base-SX single link) + 1148 9844 SK-9844 (1000Base-SX dual link) + 1148 9861 SK-9861 (1000Base-SX VF45 single link) + 1148 9862 SK-9862 (1000Base-SX VF45 dual link) +# Information got from SysKonnekt + 1148 9871 SK-9871 (1000Base-ZX single link) +# Information got from SysKonnekt + 1148 9872 SK-9872 (1000Base-ZX dual link) + 1259 2970 AT-2970SX [Allied Telesyn] + 1259 2972 AT-2970T [Allied Telesyn] + 1259 2975 AT-2970SX [Allied Telesyn] + 1259 2977 AT-2970T [Allied Telesyn] + 4320 SK-98xx Gigabit Ethernet Server Adapter 1148 5021 SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter 1148 5041 SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter 1148 5043 SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter @@ -3247,8 +3570,7 @@ 1148 5061 SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter 1148 5071 SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter 1148 9521 SK-9521 10/100/1000Base-T Adapter - 4400 SK-9Dxx Gigabit Ethernet Adapter - 4500 SK-9Mxx Gigabit Ethernet Adapter + 4400 Gigabit Ethernet 1149 Win System Corporation 114a VMIC 5579 VMIPCI-5579 (Reflective Memory Card) @@ -3364,6 +3686,7 @@ 0001 Motion TPEG Recorder/Player with audio 1166 ServerWorks 0005 CNB20-LE Host Bridge + 0006 CNB20HE Host Bridge 0007 CNB20-LE Host Bridge 0008 CNB20HE Host Bridge 0009 CNB20LE Host Bridge @@ -3377,14 +3700,20 @@ 0017 GCNB-LE Host Bridge 0200 OSB4 South Bridge 0201 CSB5 South Bridge + 4c53 1080 CT8 mainboard 0203 CSB6 South Bridge 0211 OSB4 IDE Controller 0212 CSB5 IDE Controller + 4c53 1080 CT8 mainboard 0213 CSB6 RAID/IDE Controller 0220 OSB4/CSB5 OHCI USB Controller + 4c53 1080 CT8 mainboard 0221 CSB6 OHCI USB Controller 0225 GCLE Host Bridge +# cancelled + 4c53 1080 CT8 mainboard 0227 GCLE-2 Host Bridge + 4c53 1080 CT8 mainboard 1167 Mutoh Industries Inc 1168 Thine Electronics Inc 1169 Centre for Development of Advanced Computing @@ -3435,7 +3764,9 @@ 0465 RL5c465 0466 RL5c466 0475 RL5c475 + 144d c006 vpr Matrix 170B4 CardBus bridge 0476 RL5c476 II + 1014 0185 ThinkPad A/T/X Series 104d 80df Vaio PCG-FX403 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 0477 RL5c477 @@ -3444,7 +3775,9 @@ 0522 R5C522 IEEE 1394 Controller 1014 01cf ThinkPad A30p (2653-64G) 0551 R5C551 IEEE 1394 Controller + 144d c006 vpr Matrix 170B4 0552 R5C552 IEEE 1394 Controller + 1014 0511 ThinkPad A/T/X Series 1181 Telmatics International 1183 Fujikura Ltd 1184 Forks Inc @@ -3460,8 +3793,6 @@ 1340 DFE-690TXD CardBus PC Card 1561 DRP-32TXD Cardbus PC Card 4000 DL2K Ethernet - 4c00 Gigabit Ethernet Adapter - 1186 4c00 DGE-530T Gigabit Ethernet Adapter 1187 Advanced Technology Laboratories, Inc. 1188 Shima Seiki Manufacturing Ltd. 1189 Matsushita Electronics Co Ltd @@ -3539,9 +3870,6 @@ 11aa Actel 11ab Galileo Technology Ltd. 0146 GT-64010/64010A System Controller - 4146 GT-64111 System Controller - 4320 Gigabit Ethernet Adapter - 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter 4611 GT-64115 System Controller 4620 GT-64120/64120A/64121A System Controller 4801 GT-48001 @@ -3637,6 +3965,7 @@ 0443 LT WinModem 0444 LT WinModem 0445 LT WinModem + 8086 2203 PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card) 0446 LT WinModem 0447 LT WinModem 0448 WinModem 56k @@ -3666,6 +3995,7 @@ 044e LT WinModem 044f V90 WildWire Modem 0450 LT WinModem + 1033 80a8 Versa Note Vxi 144f 4005 Magnia SG20 0451 LT WinModem 0452 LT WinModem @@ -3683,6 +4013,8 @@ 0480 Venus Modem (V90, 56KFlex) 5801 USB 5802 USS-312 USB Controller +# 4 port PCI USB Controller made by Agere (formely Lucent) + 5803 USS-344S USB Controller 5811 FW323 dead 0800 FireWire Host Bus Adapter 11c2 Sand Microelectronics @@ -3726,7 +4058,6 @@ 11d9 TEC Corporation 11da Novell 11db Sega Enterprises Ltd - 1234 Broadband Adapter 11dc Questra Corporation 11dd Crosfield Electronics Limited 11de Zoran Corporation @@ -3786,32 +4117,28 @@ 11fc Silicon Magic 11fd High Street Consultants 11fe Comtrol Corporation - 0001 Rocketport 32 port w/external I/F - 0002 Rocketport 8 port w/external I/F - 0003 Rocketport 16 port w/external I/F - 0004 Rocketport 4 port w/quad cable - 0005 Rocketport 8 port w/octa cable - 0006 Rocketport 8 port w/RJ11 connectors - 0007 Rocketport 4 port w/RJ11 connectors - 0008 Rocketport 8 port w/ DB78 SNI (Siemens) connector - 0009 Rocketport 16 port w/ DB78 SNI (Siemens) connector - 000a Rocketport Plus 4 port - 000b Rocketport Plus 8 port - 000c RocketModem 6 port - 000d RocketModem 4-port - 000e Rocketport Plus 2 port RS232 - 000f Rocketport Plus 2 port RS422 - 0801 Rocketport UPCI 32 port w/external I/F - 0802 Rocketport UPCI 8 port w/external I/F - 0803 Rocketport UPCI 16 port w/external I/F - 0805 Rocketport UPCI 8 port w/octa cable - 080C RocketModem III 8 port - 080D RocketModem III 4 port - 0903 Rocketport Compact PCI 16 port w/external I/F + 0001 RocketPort 8 Oct + 0002 RocketPort 8 Intf + 0003 RocketPort 16 Intf + 0004 RocketPort 32 Intf + 0005 RocketPort Octacable + 0006 RocketPort 8J + 0007 RocketPort 4-port + 0008 RocketPort 8-port + 0009 RocketPort 16-port + 000a RocketPort Plus Quadcable + 000b RocketPort Plus Octacable + 000c RocketPort 8-port Modem + 8015 RocketPort 4-port UART 16954 11ff Scion Corporation 1200 CSS Corporation 1201 Vista Controls Corp 1202 Network General Corp. + 4300 Gigabit Ethernet Adapter + 1202 9841 SK-9841 LX + 1202 9842 SK-9841 LX dual link + 1202 9843 SK-9843 SX + 1202 9844 SK-9843 SX dual link 1203 Bayer Corporation, Agfa Division 1204 Lattice Semiconductor Corporation 1205 Array Corporation @@ -3858,6 +4185,7 @@ 6933 OZ6933 Cardbus Controller 1025 1016 Travelmate 612 TX 6972 OZ6912 Cardbus Controller + 1179 0001 Magnia Z310 1218 Hybricon Corp. 1219 First Virtual Corporation 121a 3Dfx Interactive, Inc. @@ -3975,6 +4303,8 @@ 1242 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter 1242 656a FCX-6562 PCI-X Fibre Channel Adapter 4643 FCI-1063 Fibre Channel Adapter + 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter + 656a FCX-6562 PCI-X Fibre Channel Adapter 1243 Delphax 1244 AVM Audiovisuelles MKTG & Computer System GmbH 0700 B1 ISDN @@ -4035,6 +4365,7 @@ 1014 0166 ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard 125d 8888 Solo-1 Audio Adapter 1978 ES1978 Maestro 2E + 0e11 b112 Armada M700/E500 1033 803c ES1978 Maestro-2E Audiodrive 1033 8058 ES1978 Maestro-2E Audiodrive 1092 4000 Monster Sound MX400 @@ -4045,6 +4376,7 @@ 1989 ESS Modem 125d 1989 ESS Modem 1998 ES1983S Maestro-3i PCI Audio Accelerator + 1028 00b1 Latitude C600 1028 00e6 ES1983S Maestro-3i (Dell Inspiron 8100) 1999 ES1983S Maestro-3i PCI Modem Accelerator 199a ES1983S Maestro-3i PCI Audio Accelerator @@ -4067,8 +4399,9 @@ 3873 Prism 2.5 Wavelan chipset 1186 3501 DWL-520 Wireless PCI Adapter 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter - 1737 3874 WMP11 Wireless 802.11b PCI Adaptor + 1737 3874 WMP11 Wireless 802.11b PCI Adapter 8086 2513 Wireless 802.11b MiniPCI Adapter + 3890 D-Links DWL-g650 A1 8130 HMP8130 NTSC/PAL Video Decoder 8131 HMP8131 NTSC/PAL Video Decoder 1261 Matsushita-Kotobuki Electronics Industries, Ltd. @@ -4094,6 +4427,7 @@ 0710 SM710 LynxEM 0712 SM712 LynxEM+ 0720 SM720 Lynx3DM + 0730 SM731 Cougar3DR 0810 SM810 LynxE 0811 SM811 LynxE 0820 SM820 Lynx3D @@ -4104,6 +4438,7 @@ 1273 Hughes Network Systems 0002 DirecPC 1274 Ensoniq + 1171 ES1373 [AudioPCI] (also Creative Labs CT5803) 1371 ES1371 [AudioPCI-97] 0e11 0024 AudioPCI on Motherboard Compaq Deskpro 0e11 b1a7 ES1371, ES1373 AudioPCI @@ -4173,6 +4508,7 @@ 1277 Comstream 1278 Transtech Parallel Systems Ltd. 0701 TPE3/TM3 PowerPC Node + 0710 TPE5 PowerPC PCI board 1279 Transmeta Corporation 0295 Northbridge 0395 LongRun Northbridge @@ -4368,6 +4704,7 @@ 12ae 0001 Gigabit Ethernet-SX (Universal) 1410 0104 Gigabit Ethernet-SX PCI Adapter 0002 AceNIC Gigabit Ethernet (Copper) + 10a9 8002 Acenic Gigabit Ethernet 12ae 0002 Gigabit Ethernet-T (3C986-T) 12af TDK USA Corp 12b0 Jorge Scientific Corp @@ -4379,7 +4716,7 @@ 12b6 Natural Microsystems 12b7 Cognex Modular Vision Systems Div. - Acumen Inc. 12b8 Korg -12b9 US Robotics/3Com +12b9 5610 56K FaxModem 1006 WinModem 12b9 005c USR 56k Internal Voice WinModem (Model 3472) 12b9 005e USR 56k Internal WinModem (Models 662975) @@ -4462,16 +4799,20 @@ 00a0 ITNT2 12d3 Vingmed Sound A/S 12d4 Ulticom (Formerly DGM&S) + 0200 T1 Card 12d5 Equator Technologies 12d6 Analogic Corp 12d7 Biotronic SRL 12d8 Pericom Semiconductor 12d9 Aculab PLC + 0002 PCI Prosody + 0004 cPCI Prosody 12da True Time Inc. 12db Annapolis Micro Systems, Inc 12dc Symicron Computer Communication Ltd. 12dd Management Graphics 12de Rainbow Technologies + 0200 CryptoSwift CS200 12df SBS Technologies Inc 12e0 Chase Research 0010 ST16C654 Quad UART @@ -4584,6 +4925,7 @@ 0036 PCI-DAS64/M2/16 0037 PCI-DAS64/M3/16 004c PCI-DAS1000 + 004d PCI-QUAD04 1308 Jato Technologies Inc. 0001 NetCelerator Adapter 1308 0001 NetCelerator Adapter @@ -4669,8 +5011,13 @@ 132d Integrated Silicon Solution, Inc. 1330 MMC Networks 1331 Radisys Corp. + 8200 82600 Host Bridge + 8201 82600 IDE + 8202 82600 USB + 8210 82600 PCI Bridge 1332 Micro Memory 5415 MM-5415CN PCI Memory Module with Battery Backup + 5425 MM-5425CN PCI 64/66 Memory Module with Battery Backup 1334 Redcreek Communications, Inc 1335 Videomail, Inc 1337 Third Planet Publishing @@ -4696,6 +5043,7 @@ 134c Chori Joho System Co. Ltd 134d PCTel Inc 7890 HSP MicroModem 56 + 134d 0001 PCT789 adapter 7891 HSP MicroModem 56 134d 0001 HSP MicroModem 56 7892 HSP MicroModem 56 @@ -4755,13 +5103,12 @@ 1369 Digigram 136a High Soft Tech 136b Kawasaki Steel Corporation + ff01 KL5A72002 Motion JPEG 136c Adtek System Science Co Ltd 136d Gigalabs Inc 136f Applied Magic Inc 1370 ATL Products 1371 CNet Technology Inc - 434e GigaCard Network Adapter - 1371 434e N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) 1373 Silicon Vision Inc 1374 Silicom Ltd 1375 Argosystems Inc @@ -4782,6 +5129,7 @@ 1384 Reality Simulation Systems Inc 1385 Netgear 4100 802.11b Wireless Adapter (MA301) + 4105 MA311 802.11b wireless adapter 620a GA620 622a GA622 630a GA630 @@ -4891,6 +5239,8 @@ 13ce Cocom A/S 13cf Studio Audio & Video Ltd 13d0 Techsan Electronics Co Ltd +# http://www.b2c2inc.com/products/pc-specs.html + 2103 B2C2 Sky2PC PCI [SkyStar2] 13d1 Abocom Systems Inc ab02 ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter ab06 RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter @@ -4919,7 +5269,7 @@ 13e6 Argosy research Inc 13e7 NAC Incorporated 13e8 Chip Express Corporation -13e9 Chip Express Corporation +13e9 Intraserver Technology Inc 13ea Dallas Semiconductor 13eb Hauppauge Computer Works Inc 13ec Zydacron Inc @@ -4941,9 +5291,11 @@ 13f6 0101 CMI8338-031 PCI Audio Device 0111 CM8738 1019 0970 P6STP-FL motherboard + 1043 8035 CUSI-FX motherboard 1043 8077 CMI8738 6-channel audio controller 1043 80e2 CMI8738 6ch-MX 13f6 0111 CMI8738/C3DX PCI Audio Device + 1681 a000 Gamesurround MUSE XL 0211 CM8738 13f7 Wildfire Communications 13f8 Ad Lib Multimedia Inc @@ -4967,8 +5319,6 @@ 0100 Lava Dual Serial 0101 Lava Quatro A 0102 Lava Quatro B - 0180 Lava Octo A - 0181 Lava Octo B 0200 Lava Port Plus 0201 Lava Quad A 0202 Lava Quad B @@ -5016,6 +5366,8 @@ 141e Fanuc Ltd 141f Visiontech Ltd 1420 Psion Dacom plc + 8002 Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part) + 8003 Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part) 1421 Ads Technologies Inc 1422 Ygrec Systems Co Ltd 1423 Custom Technology Corp. @@ -5090,7 +5442,7 @@ 0001 NextMove PCI 1460 DYNARC INC 1461 Avermedia Technologies Inc -1462 Micro-star International Co Ltd +1462 Micro-Star International Co., Ltd. 1463 Fast Corporation 1464 Interactive Circuits & Systems Ltd 1465 GN NETTEST Telecom DIV. @@ -5101,6 +5453,7 @@ 146a IFR 146b Parascan Technologies Ltd 146c Ruby Tech Corp. + 1430 FE-1430TX Fast Ethernet PCI Adapter 146d Tachyon, INC. 146e Williams Electronics Games, Inc. 146f Multi Dimensional Consulting Inc @@ -5151,6 +5504,7 @@ 149b SEIKO Instruments Inc 149c OVISLINK Corp. 149d NEWTEK Inc + 0001 Video Toaster for PC 149e Mapletree Networks Inc. 149f LECTRON Co Ltd 14a0 SOFTING GmBH @@ -5177,6 +5531,14 @@ 0000 DSL NIC 14b4 PHILIPS Business Electronics B.V. 14b5 Creamware GmBH + 0200 Scope + 0300 Pulsar + 0400 Pulsar2 + 0600 Pulsar2 + 0800 DSP-Board + 0900 DSP-Board + 0a00 DSP-Board + 0b00 DSP-Board 14b6 Quantum Data Corp. 14b7 PROXIM Inc 0001 Symphony 4110 @@ -5285,6 +5647,9 @@ 0e11 009a NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T) 0e11 00c1 NC6770 Gigabit Server Adapter (PCI-X, 1000-SX) 1028 0121 Broadcom BCM5701 1000Base-T + 10a9 8010 SGI IO9 Gigabit Ethernet (Copper) + 10a9 8011 SGI Gigabit Ethernet (Copper) + 10a9 8012 SGI Gigabit Ethernet (Fiber) 10b7 1004 3C996-SX 1000Base-SX 10b7 1006 3C996B-T 1000Base-T 10b7 1007 3C1000-T 1000Base-T @@ -5302,6 +5667,7 @@ 1647 NetXtreme BCM5703 Gigabit Ethernet 0e11 0099 NC7780 1000BaseTX 0e11 009a NC7770 1000BaseTX + 10a9 8010 SGI IO9 Gigabit Ethernet (Copper) 14e4 0009 BCM5703 1000BaseTX 14e4 000a BCM5703 1000BaseSX 14e4 000b BCM5703 1000BaseTX @@ -5314,13 +5680,9 @@ 10b7 2000 3C998-T Dual Port 10/100/1000 PCI-X 10b7 3000 3C999-T Quad Port 10/100/1000 PCI-X 1166 1648 NetXtreme CIOB-E 1000Base-T - 1649 NetXtreme BCM5704S Gigabit Ethernet 164d NetXtreme BCM5702FE Gigabit Ethernet 1653 NetXtreme BCM5705 Gigabit Ethernet - 1654 NetXtreme BCM5705 Gigabit Ethernet 165d NetXtreme BCM5705M Gigabit Ethernet - 165e NetXtreme BCM5705M Gigabit Ethernet - 166e NetXtreme BCM5705F Gigabit Ethernet 1696 NetXtreme BCM5782 Gigabit Ethernet 14e4 000d NetXtreme BCM5782 1000Base-T 169c NetXtreme BCM5788 Gigabit Ethernet @@ -5345,13 +5707,14 @@ 16c7 NetXtreme BCM5703 Gigabit Ethernet 14e4 0009 NetXtreme BCM5703 1000Base-T 14e4 000a NetXtreme BCM5703 1000Base-SX - 170d NetXtreme BCM5901 Gigabit Ethernet - 170e NetXtreme BCM5901 Gigabit Ethernet 4210 BCM4210 iLine10 HomePNA 2.0 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem 4212 BCM4212 v.90 56k modem 4301 BCM4301 802.11b + 4320 BCM94306 802.11g + 1737 4320 WPC54G 4401 BCM4401 100Base-T + 1043 80a8 A7V8X motherboard 4402 BCM4402 Integrated 10/100BaseT 4410 BCM4413 iLine32 HomePNA 2.0 4411 BCM4413 V.90 56k modem @@ -5440,6 +5803,9 @@ 122d 4302 Dell MP3930V-W(C) MiniPCI 1610 ADSL AccessRunner PCI Arbitration Device 1611 AccessRunner PCI ADSL Interface Device + 1620 ADSL AccessRunner V2 PCI Arbitration Device + 1621 AccessRunner V2 PCI ADSL Interface Device + 1622 AccessRunner V2 PCI ADSL Yukon WAN Adapter 1803 HCF 56k Modem 0e11 0023 623-LAN Grizzly 0e11 0043 623-LAN Yogi @@ -5505,11 +5871,6 @@ 14f1 2004 Dynalink 56PMi 8234 RS8234 ATM SAR Controller [ServiceSAR Plus] 14f2 MOBILITY Electronics - 0120 EV1000 bridge - 0121 EV1000 Parallel port - 0122 EV1000 Serial port - 0123 EV1000 Keyboard controller - 0124 EV1000 Mouse controller 14f3 BROADLOGIC 14f4 TOKYO Electronic Industry CO Ltd 14f5 SOPAC Ltd @@ -5582,6 +5943,8 @@ 1522 0400 RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem 1522 0500 RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem 1522 0600 RockForce+ 2 Port V.90 Data/Fax/Voice Modem + 1522 0700 RockForce+ 4 Port V.90 Data/Fax/Voice Modem + 1522 0800 RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem 1523 MUSIC Semiconductors 1524 ENE Technology Inc 1211 CB1211 Cardbus Controller @@ -5618,6 +5981,7 @@ 1541 MACHONE Communications 1542 VIVID Technology Inc 1543 SILICON Laboratories + 3052 Intel 537 [Winmodem] 4c22 Si3036 MC'97 DAA 1544 DCM DATA Systems 1545 VISIONTEK @@ -5858,6 +6222,7 @@ 1638 Standard Microsystems Corp [SMC] 1100 SMC2602W EZConnect / Addtron AWA-100 163c Smart Link Ltd. + 3052 SmartLink SmartPCI562 56K Modem 5449 SmartPCI561 Modem 1657 Brocade Communications Systems, Inc. 165a Epix Inc @@ -5871,6 +6236,8 @@ 16ab Global Sun Technology Inc 1102 PCMCIA-to-PCI Wireless Network Bridge 16be Creatix Polymedia GmbH +16ca CENATEK Inc + 0001 Rocket Drive DL 16ec U.S. Robotics 3685 Wireless Access PCI Adapter Model 022415 16f6 VideoTele.com, Inc. @@ -5879,16 +6246,10 @@ 170c YottaYotta Inc. 172a Accelerated Encryption 1737 Linksys - 1032 Gigabit Network Adapter - 1737 0015 EG1032 v2 Instant Gigabit Network Adapter - 1064 Gigabit Network Adapter - 1737 0016 EG1064 v2 Instant Gigabit Network Adapter 173b Altima (nee Broadcom) 03e8 AC1000 Gigabit Ethernet - 03e9 AC1001 Gigabit Ethernet 03ea AC9100 Gigabit Ethernet 173b 0001 AC1002 - 03eb AC1003 Gigabit Ethernet 1743 Peppercon AG 8139 ROL/F-100 Fast Ethernet Adapter with ROL 174b PC Partner Limited @@ -5904,6 +6265,8 @@ 0006 AMCC HOTlink 1799 Belkin 17af Hightech Information System Ltd. +17cc NetChip Technology, Inc + 2280 USB 2.0 1813 Ambient Technologies Inc 4000 HaM controllerless modem 16be 0001 V9x HAM Data Fax Modem @@ -5911,6 +6274,11 @@ 16be 0002 V9x HAM 1394 1851 Microtune, Inc. 1852 Anritsu Corp. +1888 Varisys Ltd + 0301 VMFX1 FPGA PMC module + 0601 VSM2 dual PMC carrier + 0710 VS14x series PowerPC PCI board + 0720 VS24x series PowerPC PCI board 1a08 Sierra semiconductor 0000 SC15064 1b13 Jaton Corp @@ -5923,7 +6291,12 @@ 2020 DC-390 690c 690c dc29 DC290 +1fc0 Tumsan Oy + 0300 E2200 Dual E1/Rawpipe Card +2000 Smart Link Ltd. 2001 Temporal Research Ltd +2003 Smart Link Ltd. +2004 Smart Link Ltd. 21c3 21st Century Computer Corp. 2348 Racore 2010 8142 100VG/AnyLAN @@ -5935,7 +6308,15 @@ 3000 Hansol Electronics Inc. 3142 Post Impression Systems. 3388 Hint Corp - 0021 HB1-SE33 PCI-PCI Bridge + 0013 HiNT HC4 PCI to ISDN bridge, Multimedia audio controller + 0014 HiNT HC4 PCI to ISDN bridge, Network controller + 0020 HB6 Universal PCI-PCI bridge (transparent mode) + 0021 HB6 Universal PCI-PCI bridge (non-transparent mode) + 4c53 1050 CT7 mainboard + 4c53 1080 CT8 mainboard + 4c53 3010 PPCI mezzanine (32-bit PMC) + 101a E.Band [AudioTrak Inca88] + 101b E.Band [AudioTrak Inca88] 8011 VXPro II Chipset 3388 8011 VXPro II Chipset CPU to PCI Bridge 8012 VXPro II Chipset @@ -5995,6 +6376,7 @@ 0100 AladdinCARD 0200 CPC 4444 Internext Compression Inc + 0803 iTVC15 MPEG-2 Encoder 4468 Bridgeport machines 4594 Cogetec Informatique Inc 45fb Baldor Electric Company @@ -6040,6 +6422,7 @@ 5143 Qualcomm Inc 5145 Ensoniq (Old) 3031 Concert AudioPCI +5168 Animation Technologies Inc. 5301 Alliance Semiconductor Corp. 0001 ProMotion aT3D 5333 S3 Inc. @@ -6150,6 +6533,7 @@ 8c12 86C270-294 Savage/IX-MV 1014 017f ThinkPad T20 8c13 86C270-294 Savage/IX + 1179 0001 Magnia Z310 8c22 SuperSavage MX/128 8c24 SuperSavage MX/64 8c26 SuperSavage MX/64C @@ -6160,10 +6544,10 @@ 8c2e SuperSavage IX/C SDR 1014 01fc ThinkPad T23 (2647-4MG) 8c2f SuperSavage IX/C DDR -# Integrated in VIA ProSavage PN133 North Bridge - 8d01 VT8603 [ProSavage PN133] AGP4X VGA Controller (Twister) + 8d01 86C380 [ProSavageDDR K4M266] 8d02 VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK) - 8d04 VT8751 [ProSavageDDR P4M266] VGA Controller + 8d03 VT8751 [ProSavageDDR P4M266] + 8d04 VT8375 [ProSavage8 KM266/KL266] 9102 86C410 Savage 2000 1092 5932 Viper II Z200 1092 5934 Viper II Z200 @@ -6175,6 +6559,7 @@ 1092 5a57 Viper II Z200 ca00 SonicVibes 544c Teralogic Inc + 0350 TL880-based HDTV/ATSC tuner 5455 Technische University Berlin 4458 S5933 5519 Cnet Technologies, Inc. @@ -6182,6 +6567,7 @@ 0001 I-30xx Scanner Interface 5555 Genroco, Inc 0003 TURBOstor HFP-832 [HiPPI NIC] +5654 VoiceTronix Pty Ltd 5700 Netpower 6356 UltraStor 6374 c't Magazin für Computertechnik @@ -6257,13 +6643,14 @@ 1029 82559 Ethernet Controller 1030 82559 InBusiness 10/100 1031 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller - 1014 0209 ThinkPad A30p/T30 + 1014 0209 ThinkPad A/T/X Series 104d 80e7 Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 107b 5350 EtherExpress PRO/100 VE 1179 0001 EtherExpress PRO/100 VE 144d c000 EtherExpress PRO/100 VE 144d c001 EtherExpress PRO/100 VE 144d c003 EtherExpress PRO/100 VE + 144d c006 vpr Matrix 170B4 1032 82801CAM (ICH3) PRO/100 VE Ethernet Controller 1033 82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller 1034 82801CAM (ICH3) PRO/100 VM Ethernet Controller @@ -6279,18 +6666,20 @@ 103e 82801BD PRO/100 VM (MOB) Ethernet Controller 1040 536EP Data Fax Modem 16be 1040 V.9X DSP Data Fax Modem - 1048 82597EX 10GbE Ethernet Controller - 8086 a01f PRO/10GbE LR Server Adapter - 8086 a11f PRO/10GbE LR Server Adapter + 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter 1059 82551QM Ethernet Controller 1130 82815 815 Chipset Host Bridge and Memory Controller Hub 1025 1016 Travelmate 612 TX 1043 8027 TUSL2-C Mainboard 104d 80df Vaio PCG-FX403 + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 1131 82815 815 Chipset AGP Bridge 1132 82815 CGC [Chipset Graphics Controller] 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 + 8086 4532 D815EEA2 Mainboard + 8086 4557 D815EGEW Mainboard 1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller 8086 1161 82806AA PCI64 Hub APIC 1162 Xscale 80200 Big Endian Companion Chip @@ -6475,6 +6864,7 @@ 8086 8000 82806AA PCI64 Hub Controller (HRes) 1460 82870P2 P64H2 Hub PCI Bridge 1461 82870P2 P64H2 I/OxAPIC + 15d9 3480 P4DP6 1462 82870P2 P64H2 Hot Plug Controller 1960 80960RP [i960RP Microprocessor] 101e 0431 MegaRAID 431 RAID Controller @@ -6526,23 +6916,33 @@ 2428 82801AB PCI Bridge 2440 82801BA ISA Bridge (LPC) 2442 82801BA/BAM USB (Hub #1) + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 2443 82801BA/BAM SMBus + 1014 01c6 Netvista A40/A40p 1025 1016 Travelmate 612 TX 1043 8027 TUSL2-C Mainboard 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 2444 82801BA/BAM USB (Hub #2) 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard 2445 82801BA/BAM AC'97 Audio + 1014 01c6 Netvista A40/A40p 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 1462 3370 STAC9721 AC 147b 0507 TH7II-RAID - 2446 82801BA/BAM AC'97 Modem + 8086 4557 D815EGEW Mainboard + 2446 Intel 537 [82801BA/BAM AC'97 Modem] 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 2448 82801BAM/CAM PCI Bridge @@ -6560,8 +6960,12 @@ 1014 023d EtherExpress PRO/100 VE 1014 0244 EtherExpress PRO/100 VE 1014 0245 EtherExpress PRO/100 VE + 1014 0265 PRO/100 VE Desktop Connection + 1014 0267 PRO/100 VE Desktop Connection + 1014 026a PRO/100 VE Desktop Connection 109f 315d EtherExpress PRO/100 VE 109f 3181 EtherExpress PRO/100 VE + 1179 ff01 PRO/100 VE Network Connection 1186 7801 EtherExpress PRO/100 VE 144d 2602 HomePNA 1M CNR 8086 3010 EtherExpress PRO/100 VE @@ -6577,10 +6981,13 @@ 1025 1016 Travelmate 612TX 104d 80df Vaio PCG-FX403 244b 82801BA IDE U100 + 1014 01c6 Netvista A40/A40p 1043 8027 TUSL2-C Mainboard 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 244c 82801BAM ISA Bridge (LPC) - 244e 82801BA/CA/DB PCI Bridge + 244e 82801BA/CA/DB/EB PCI Bridge 2450 82801E ISA Bridge (LPC) 2452 82801E USB 2453 82801E SMBus @@ -6588,44 +6995,80 @@ 245b 82801E IDE U100 245d 82801E Ethernet Controller 1 245e 82801E PCI Bridge - 2480 82801CA ISA Bridge (LPC) + 2480 82801CA LPC Interface Controller 2482 82801CA/CAM USB (Hub #1) - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2483 82801CA/CAM SMBus - 1014 0220 ThinkPad T23/A30p/T30 + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2483 82801CA/CAM SMBus Controller + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 2484 82801CA/CAM USB (Hub #2) - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2485 82801CA/CAM AC'97 Audio + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2485 82801CA/CAM AC'97 Audio Controller 1014 0222 ThinkPad T23 (2647-4MG) or A30p (2653-64G) 1014 0508 ThinkPad T30 + 1014 051c ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2486 82801CA/CAM AC'97 Modem - 1014 0223 ThinkPad A30p (2653-64G) + 144d c006 vpr Matrix 170B4 + 2486 82801CA/CAM AC'97 Modem Controller + 1014 0223 ThinkPad A/T/X Series 1014 0503 ThinkPad R31 2656BBG - 1014 051a ThinkPad T30 + 1014 051a ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 1179 0001 Toshiba Satellite 1110 Z15 internal Modem 134d 4c21 Dell Inspiron 2100 internal modem + 144d 2115 vpr Matrix 170B4 internal modem 14f1 5421 MD56ORD V.92 MDC Modem 2487 82801CA/CAM USB (Hub #3) - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 248a 82801CAM IDE U100 - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 248b 82801CA IDE U100 + 8086 1958 vpr Matrix 170B4 + 248b 82801CA Ultra ATA Storage Controller + 15d9 3480 P4DP6 248c 82801CAM ISA Bridge (LPC) - 24c0 82801DB ISA Bridge (LPC) + 24c0 82801DB LPC Interface Controller + 1462 5800 845PE Max (MS-6580) 24c2 82801DB USB (Hub #1) - 24c3 82801DB SMBus + 1462 5800 845PE Max (MS-6580) + 24c3 82801DB/DBM SMBus Controller + 1462 5800 845PE Max (MS-6580) 24c4 82801DB USB (Hub #2) - 24c5 82801DB AC'97 Audio - 24c6 82801DB AC'97 Modem + 1462 5800 845PE Max (MS-6580) + 24c5 82801DB AC'97 Audio Controller + 1462 5800 845PE Max (MS-6580) + 24c6 82801DB AC'97 Modem Controller 24c7 82801DB USB (Hub #3) - 24cb 82801DB ICH4 IDE - 24cd 82801DB USB EHCI Controller + 1462 5800 845PE Max (MS-6580) + 24ca 82801DBM Ultra ATA Storage Controller + 24cb 82801DB Ultra ATA Storage Controller + 1462 5800 845PE Max (MS-6580) + 24cc 82801DBM LPC Interface Controller + 24cd 82801DB USB2 + 1462 3981 845PE Max (MS-6580) Onboard USB EHCI Controller + 24d0 82801EB LPC Interface Controller + 24d1 82801EB Ultra ATA Storage Controller + 24d2 82801EB USB + 24d3 82801EB SMBus Controller + 24d4 82801EB USB + 24d5 82801EB AC'97 Audio Controller + 24d6 82801EB AC'97 Modem Controller + 24d7 82801EB USB + 24db 82801EB Ultra ATA Storage Controller + 24dc 82801EB LPC Interface Controller + 24dd 82801EB USB2 + 24de 82801EB USB 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1028 0095 Precision Workstation 220 Chipset 1043 801c P3C-2000 system chipset @@ -6641,24 +7084,48 @@ 2532 82850 850 (Tehama) Chipset AGP Bridge 2533 82860 860 (Wombat) Chipset AGP Bridge 2534 82860 860 (Wombat) Chipset PCI Bridge - 2540 e7500 [Plumas] DRAM Controller - 2541 e7500 [Plumas] DRAM Controller Error Reporting - 2543 e7500 [Plumas] HI_B Virtual PCI Bridge (F0) - 2544 e7500 [Plumas] HI_B Virtual PCI Bridge (F1) - 2545 e7500 [Plumas] HI_C Virtual PCI Bridge (F0) - 2546 e7500 [Plumas] HI_C Virtual PCI Bridge (F1) - 2547 e7500 [Plumas] HI_D Virtual PCI Bridge (F0) - 2548 e7500 [Plumas] HI_D Virtual PCI Bridge (F1) + 2540 E7500 Memory Controller Hub + 15d9 3480 P4DP6 + 2541 E7000 Series Host RASUM Controller + 15d9 3480 P4DP6 + 2543 E7000 Series Hub Interface B PCI-to-PCI Bridge + 2544 E7000 Series Hub Interface B RASUM Controller + 2545 E7000 Series Hub Interface C PCI-to-PCI Bridge + 2546 E7000 Series Hub Interface C RASUM Controller + 2547 E7000 Series Hub Interface D PCI-to-PCI Bridge + 2548 E7000 Series Hub Interface D RASUM Controller + 254c E7501 Memory Controller Hub + 2550 E7505 Memory Controller Hub + 2551 E7000 Series RAS Controller + 2552 E7000 Series Processor to AGP Controller + 2553 E7000 Series Hub Interface B PCI-to-PCI Bridge + 2554 E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller + 255d E7205 Memory Controller Hub 2560 82845G/GL [Brookdale-G] Chipset Host Bridge + 1462 5800 845PE Max (MS-6580) 2561 82845G/GL [Brookdale-G] Chipset AGP Bridge 2562 82845G/GL [Brookdale-G] Chipset Integrated Graphics Device + 2570 82865G/PE/P Processor to I/O Controller + 2571 82865G/PE/P Processor to AGP Controller + 2572 82865G Integrated Graphics Device + 2573 82865G/PE/P Processor to PCI to CSA Bridge + 2576 82864G/PE/P Processor to I/O Memory Interface + 2578 82875P Memory Controller Hub + 2579 82875P Processor to AGP Controller + 257b 82875P Processor to PCI to CSA Bridge + 257e 82875P Processor to I/O Memory Interface 3092 Integrated RAID + 3340 82855PM Processor to I/O Controller + 3341 82855PM Processor to AGP Controller 3575 82830 830 Chipset Host Bridge - 1014 021d ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 1014 021d ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 3576 82830 830 Chipset AGP Bridge 3577 82830 CGC [Chipset Graphics Controller] + 1014 0513 ThinkPad A/T/X Series 3578 82830 830 Chipset Host Bridge + 3580 82852/855GM Host Bridge + 3582 82852/855GM Integrated Graphics Device 5200 EtherExpress PRO/100 Intelligent Server 5201 EtherExpress PRO/100 Intelligent Server 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter @@ -6674,6 +7141,7 @@ 7113 82371AB/EB/MB PIIX4 ACPI 7120 82810 GMCH [Graphics Memory Controller Hub] 7121 82810 CGC [Chipset Graphics Controller] + 8086 4341 Cayman (CA810) Mainboard 7122 82810 DC-100 GMCH [Graphics Memory Controller Hub] 7123 82810 DC-100 CGC [Chipset Graphics Controller] 7124 82810E DC-133 GMCH [Graphics Memory Controller Hub] @@ -6685,6 +7153,7 @@ 7181 440LX/EX - 82443LX/EX AGP bridge 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge 0e11 0500 Armada 1750 Laptop System Chipset + 0e11 b110 Armada M700 1179 0001 Toshiba Tecra 8100 Laptop System Chipset 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) @@ -6761,9 +7230,6 @@ 5478 AIC-7850 5575 AVA-2930 5578 AIC-7855 - 5647 ANA-7711 TCP Offload Engine - 9004 7710 ANA-7711F TCP Offload Engine - Optical - 9004 7711 ANA-7711LP TCP Offload Engine - Copper 5675 AIC-755x 5678 AIC-7856 5775 AIC-755x @@ -6805,6 +7271,8 @@ 7478 AHA-2944/2944W / AIC-7874 7578 AHA-3944/3944W / AIC-7875 7678 AHA-4944W/UW / AIC-7876 + 7710 ANA-7711F Network Accelerator Card (NAC) - Optical + 7711 ANA-7711C Network Accelerator Card (NAC) - Copper 7778 AIC-787x 7810 AIC-7810 7815 AIC-7815 RAID+Memory Controller IC @@ -6881,6 +7349,8 @@ 9005 62a1 19160 Ultra160 SCSI Controller 0083 AIC-7892D U160/m 008f AIC-7892P U160/m + 1179 0001 Magnia Z310 + 15d9 9005 Onboard SCSI Host Adapter 00c0 AHA-3960D / AIC-7899A U160/m 0e11 f620 Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter 9005 f620 AHA-3960D U160/m @@ -6890,6 +7360,8 @@ 1028 00c5 PowerEdge 2550 00cf AIC-7899P U160/m 1028 00d1 PowerEdge 2550 + 10f1 2462 Thunder K7 S2462 + 15d9 9005 Onboard SCSI Host Adapter 0250 ServeRAID Controller 1014 0279 ServeRAID-xx 1014 028c ServeRAID-xx @@ -6906,11 +7378,18 @@ 8014 ASC-29320LP U320 801e AIC-7901A U320 801f AIC-7902 U320 + 8080 ASC-29320A U320 w/HostRAID + 808f AIC-7901 U320 w/HostRAID 8090 ASC-39320 U320 w/HostRAID 8091 ASC-39320D U320 w/HostRAID 8092 ASC-29320 U320 w/HostRAID 8093 ASC-29320B U320 w/HostRAID 8094 ASC-29320LP U320 w/HostRAID + 8095 ASC-39320(B) U320 w/HostRAID + 8096 ASC-39320A U320 w/HostRAID + 8097 ASC-29320ALP U320 w/HostRAID + 809c ASC-39320D(B) U320 w/HostRAID + 809d AIC-7902(B) U320 w/HostRAID 809e AIC-7901A U320 w/HostRAID 809f AIC-7902 U320 w/HostRAID 907f Atronics @@ -6953,7 +7432,7 @@ e000 Winbond e000 W89C940 e159 Tiger Jet Network Inc. - 0001 Model 300 128k [Catawba TJ] + 0001 Intel 537 0059 0001 128k ISDN-S/T Adapter 0059 0003 128k ISDN-U Adapter 0002 Tiger100APC ISDN chipset @@ -6999,7 +7478,9 @@ facd KONA HD SMPTE 292M I/O fa57 Fast Search & Transfer ASA febd Ultraview Corp. -feda Epigram Inc +feda Broadcom Inc (nee Epigram) + a0fa BCM4210 iLine10 HomePNA 2.0 + a10e BCM4230 iLine10 HomePNA 2.0 fffe VMWare Inc 0710 Virtual SVGA ffff Illegal Vendor ID diff -urN linux-2.6.2-rc2/drivers/pci/probe.c linux-2.6.2-rc3/drivers/pci/probe.c --- linux-2.6.2-rc2/drivers/pci/probe.c 2004-01-08 22:59:47.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/probe.c 2004-01-30 18:49:22.000000000 -0800 @@ -6,6 +6,7 @@ #include #include #include +#include #undef DEBUG @@ -25,6 +26,39 @@ LIST_HEAD(pci_devices); /* + * PCI Bus Class + */ +static void release_pcibus_dev(struct class_device *class_dev) +{ + struct pci_bus *pci_bus = to_pci_bus(class_dev); + if (pci_bus->bridge) + put_device(pci_bus->bridge); + kfree(pci_bus); +} + +static struct class pcibus_class = { + .name = "pci_bus", + .release = &release_pcibus_dev, +}; + +static int __init pcibus_class_init(void) +{ + return class_register(&pcibus_class); +} +postcore_initcall(pcibus_class_init); + +/* + * PCI Bus Class Devices + */ +static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf) +{ + cpumask_t cpumask = pcibus_to_cpumask((to_pci_bus(class_dev))->number); + + return sprintf(buf, "%lx\n", (unsigned long)cpumask); +} +static CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL); + +/* * Translate the low bits of the PCI base * to the resource type */ @@ -238,37 +272,40 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) { struct pci_bus *child; + int i; /* * Allocate a new bus, and inherit stuff from the parent.. */ child = pci_alloc_bus(); + if (!child) + return NULL; - if (child) { - int i; - - child->self = bridge; - child->parent = parent; - child->ops = parent->ops; - child->sysdata = parent->sysdata; - child->dev = &bridge->dev; - - /* - * Set up the primary, secondary and subordinate - * bus numbers. - */ - child->number = child->secondary = busnr; - child->primary = parent->secondary; - child->subordinate = 0xff; - - /* Set up default resource pointers and names.. */ - for (i = 0; i < 4; i++) { - child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; - child->resource[i]->name = child->name; - } + child->self = bridge; + child->parent = parent; + child->ops = parent->ops; + child->sysdata = parent->sysdata; + child->bridge = get_device(&bridge->dev); + + child->class_dev.class = &pcibus_class; + sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr); + class_device_register(&child->class_dev); + class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity); - bridge->subordinate = child; + /* + * Set up the primary, secondary and subordinate + * bus numbers. + */ + child->number = child->secondary = busnr; + child->primary = parent->secondary; + child->subordinate = 0xff; + + /* Set up default resource pointers and names.. */ + for (i = 0; i < 4; i++) { + child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; + child->resource[i]->name = child->name; } + bridge->subordinate = child; return child; } @@ -300,25 +337,31 @@ struct pci_bus *child; int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); u32 buses; + u16 bctl; pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", pci_name(dev), buses & 0xffffff, pass); + /* Disable MasterAbortMode during probing to avoid reporting + of bus errors (in some architectures) */ + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl); + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, + bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); + if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { - unsigned int cmax; + unsigned int cmax, busnr; /* * Bus already configured by firmware, process it in the first * pass and just note the configuration. */ if (pass) return max; - child = pci_alloc_child_bus(bus, dev, 0); + busnr = (buses >> 8) & 0xFF; + child = pci_alloc_child_bus(bus, dev, busnr); child->primary = buses & 0xFF; - child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; - child->number = child->secondary; cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; } else { @@ -370,6 +413,8 @@ pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); + sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); return max; @@ -508,7 +553,7 @@ memset(dev, 0, sizeof(struct pci_dev)); dev->bus = bus; dev->sysdata = bus->sysdata; - dev->dev.parent = bus->dev; + dev->dev.parent = bus->bridge; dev->dev.bus = &pci_bus_type; dev->devfn = devfn; dev->hdr_type = hdr_type & 0x7f; @@ -535,6 +580,30 @@ return dev; } +struct pci_dev * __devinit +pci_scan_single_device(struct pci_bus *bus, int devfn) +{ + struct pci_dev *dev; + + dev = pci_scan_device(bus, devfn); + pci_scan_msi_device(dev); + + if (!dev) + return NULL; + + /* Fix up broken headers */ + pci_fixup_device(PCI_FIXUP_HEADER, dev); + + /* + * Add the device to our list of discovered devices + * and the bus list for fixup functions, etc. + */ + INIT_LIST_HEAD(&dev->global_list); + list_add_tail(&dev->bus_list, &bus->devices); + + return dev; +} + /** * pci_scan_slot - scan a PCI slot on a bus for devices. * @bus: PCI bus to scan @@ -551,34 +620,25 @@ for (func = 0; func < 8; func++, devfn++) { struct pci_dev *dev; - dev = pci_scan_device(bus, devfn); - pci_scan_msi_device(dev); - if (func == 0) { - if (!dev) - break; + dev = pci_scan_single_device(bus, devfn); + if (dev) { + nr++; + + /* + * If this is a single function device, + * don't scan past the first function. + */ + if (!dev->multifunction) { + if (func > 0) { + dev->multifunction = 1; + } else { + break; + } + } } else { - if (!dev) - continue; - dev->multifunction = 1; + if (func == 0) + break; } - - /* Fix up broken headers */ - pci_fixup_device(PCI_FIXUP_HEADER, dev); - - /* - * Add the device to our list of discovered devices - * and the bus list for fixup functions, etc. - */ - INIT_LIST_HEAD(&dev->global_list); - list_add_tail(&dev->bus_list, &bus->devices); - nr++; - - /* - * If this is a single function device, - * don't scan past the first function. - */ - if (!dev->multifunction) - break; } return nr; } @@ -635,13 +695,14 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; + struct device *dev; b = pci_alloc_bus(); if (!b) return NULL; - b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL); - if (!b->dev){ + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev){ kfree(b); return NULL; } @@ -652,17 +713,24 @@ if (pci_find_bus(pci_domain_nr(b), bus)) { /* If we already got to this bus through a different bridge, ignore it */ DBG("PCI: Bus %02x already known\n", bus); - kfree(b->dev); + kfree(dev); kfree(b); return NULL; } - list_add_tail(&b->node, &pci_root_buses); - memset(b->dev,0,sizeof(*(b->dev))); - b->dev->parent = parent; - sprintf(b->dev->bus_id,"pci%04x:%02x", pci_domain_nr(b), bus); - device_register(b->dev); + memset(dev, 0, sizeof(*dev)); + dev->parent = parent; + sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus); + device_register(dev); + b->bridge = get_device(dev); + + b->class_dev.class = &pcibus_class; + sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus); + class_device_register(&b->class_dev); + class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity); + + sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge"); b->number = b->secondary = bus; b->resource[0] = &ioport_resource; @@ -681,4 +749,5 @@ EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_bridge); +EXPORT_SYMBOL(pci_scan_single_device); #endif diff -urN linux-2.6.2-rc2/drivers/pci/search.c linux-2.6.2-rc3/drivers/pci/search.c --- linux-2.6.2-rc2/drivers/pci/search.c 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pci/search.c 2004-01-30 18:49:22.000000000 -0800 @@ -104,6 +104,41 @@ } /** + * pci_get_slot - locate PCI device for a given PCI slot + * @bus: PCI bus on which desired PCI device resides + * @devfn: encodes number of PCI slot in which the desired PCI + * device resides and the logical device number within that slot + * in case of multi-function devices. + * + * Given a PCI bus and slot/function number, the desired PCI device + * is located in the list of PCI devices. + * If the device is found, its reference count is increased and this + * function returns a pointer to its data structure. The caller must + * decrement the reference count by calling pci_dev_put(). + * If no device is found, %NULL is returned. + */ +struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) +{ + struct list_head *tmp; + struct pci_dev *dev; + + WARN_ON(in_interrupt()); + spin_lock(&pci_bus_lock); + + list_for_each(tmp, &bus->devices) { + dev = pci_dev_b(tmp); + if (dev->devfn == devfn) + goto out; + } + + dev = NULL; + out: + pci_dev_get(dev); + spin_unlock(&pci_bus_lock); + return dev; +} + +/** * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids @@ -319,3 +354,4 @@ EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); +EXPORT_SYMBOL(pci_get_slot); diff -urN linux-2.6.2-rc2/drivers/pcmcia/sa1100_cerf.c linux-2.6.2-rc3/drivers/pcmcia/sa1100_cerf.c --- linux-2.6.2-rc2/drivers/pcmcia/sa1100_cerf.c 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/drivers/pcmcia/sa1100_cerf.c 2004-01-30 18:49:22.000000000 -0800 @@ -11,27 +11,25 @@ #include #include #include +#include #include #include #include +#include #include "sa1100_generic.h" -#ifdef CONFIG_SA1100_CERF_CPLD -#define CERF_SOCKET 0 -#else #define CERF_SOCKET 1 -#endif static struct pcmcia_irqs irqs[] = { - { CERF_SOCKET, IRQ_GPIO_CF_CD, "CF_CD" }, - { CERF_SOCKET, IRQ_GPIO_CF_BVD2, "CF_BVD2" }, - { CERF_SOCKET, IRQ_GPIO_CF_BVD1, "CF_BVD1" } + { CERF_SOCKET, CERF_IRQ_GPIO_CF_CD, "CF_CD" }, + { CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD2, "CF_BVD2" }, + { CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD1, "CF_BVD1" } }; static int cerf_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt) { - skt->irq = IRQ_GPIO_CF_IRQ; + skt->irq = CERF_IRQ_GPIO_CF_IRQ; return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); } @@ -46,13 +44,13 @@ { unsigned long levels = GPLR; - state->detect=((levels & GPIO_CF_CD)==0)?1:0; - state->ready=(levels & GPIO_CF_IRQ)?1:0; - state->bvd1=(levels & GPIO_CF_BVD1)?1:0; - state->bvd2=(levels & GPIO_CF_BVD2)?1:0; - state->wrprot=0; - state->vs_3v=1; - state->vs_Xv=0; + state->detect = (levels & CERF_GPIO_CF_CD) ?0:1; + state->ready = (levels & CERF_GPIO_CF_IRQ) ?1:0; + state->bvd1 = (levels & CERF_GPIO_CF_BVD1)?1:0; + state->bvd2 = (levels & CERF_GPIO_CF_BVD2)?1:0; + state->wrprot = 0; + state->vs_3v = 1; + state->vs_Xv = 0; } static int @@ -61,13 +59,8 @@ { switch (state->Vcc) { case 0: - break; - case 50: case 33: -#ifdef CONFIG_SA1100_CERF_CPLD - GPCR = GPIO_PWR_SHUTDOWN; -#endif break; default: @@ -77,13 +70,9 @@ } if (state->flags & SS_RESET) { -#ifdef CONFIG_SA1100_CERF_CPLD - GPSR = GPIO_CF_RESET; -#endif + GPSR = CERF_GPIO_CF_RESET; } else { -#ifdef CONFIG_SA1100_CERF_CPLD - GPCR = GPIO_CF_RESET; -#endif + GPCR = CERF_GPIO_CF_RESET; } return 0; @@ -101,8 +90,8 @@ static struct pcmcia_low_level cerf_pcmcia_ops = { .owner = THIS_MODULE, - .init = cerf_pcmcia_hw_init, - .shutdown = cerf_pcmcia_hw_shutdown, + .hw_init = cerf_pcmcia_hw_init, + .hw_shutdown = cerf_pcmcia_hw_shutdown, .socket_state = cerf_pcmcia_socket_state, .configure_socket = cerf_pcmcia_configure_socket, diff -urN linux-2.6.2-rc2/drivers/serial/sunsab.c linux-2.6.2-rc3/drivers/serial/sunsab.c --- linux-2.6.2-rc2/drivers/serial/sunsab.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/serial/sunsab.c 2004-01-30 18:49:23.000000000 -0800 @@ -101,13 +101,16 @@ union sab82532_irq_status *stat, struct pt_regs *regs) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = NULL; unsigned char buf[32]; int saw_console_brk = 0; int free_fifo = 0; int count = 0; int i; + if (up->port.info != NULL) /* Unopened serial console */ + tty = up->port.info->tty; + /* Read number of BYTES (Character + Status) available. */ if (stat->sreg.isr0 & SAB82532_ISR0_RPF) { count = SAB82532_RECV_FIFO_SIZE; @@ -142,6 +145,11 @@ for (i = 0; i < count; i++) { unsigned char ch = buf[i]; + if (tty == NULL) { + uart_handle_sysrq_char(&up->port, ch, regs); + continue; + } + if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) @@ -217,7 +225,8 @@ } } - tty_flip_buffer_push(tty); + if (tty) + tty_flip_buffer_push(tty); if (saw_console_brk) sun_do_break(); diff -urN linux-2.6.2-rc2/drivers/usb/Kconfig linux-2.6.2-rc3/drivers/usb/Kconfig --- linux-2.6.2-rc2/drivers/usb/Kconfig 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/Kconfig 2004-01-30 18:49:23.000000000 -0800 @@ -7,7 +7,7 @@ # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. config USB tristate "Support for USB" - depends on PCI || SA1111 + depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 ---help--- Universal Serial Bus (USB) is a specification for a serial bus subsystem which offers higher speeds and more features than the diff -urN linux-2.6.2-rc2/drivers/usb/core/hub.c linux-2.6.2-rc3/drivers/usb/core/hub.c --- linux-2.6.2-rc2/drivers/usb/core/hub.c 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/core/hub.c 2004-01-30 18:49:23.000000000 -0800 @@ -31,6 +31,7 @@ #include #include +#include "usb.h" #include "hcd.h" #include "hub.h" @@ -1316,8 +1317,8 @@ kfree(descriptor); usb_destroy_configuration(dev); - ret = usb_get_device_descriptor(dev); - if (ret < sizeof(dev->descriptor)) { + ret = usb_get_device_descriptor(dev, sizeof(dev->descriptor)); + if (ret != sizeof(dev->descriptor)) { if (ret < 0) err("unable to get device %s descriptor " "(error=%d)", dev->devpath, ret); diff -urN linux-2.6.2-rc2/drivers/usb/core/message.c linux-2.6.2-rc3/drivers/usb/core/message.c --- linux-2.6.2-rc2/drivers/usb/core/message.c 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/core/message.c 2004-01-30 18:49:23.000000000 -0800 @@ -546,10 +546,10 @@ * * Gets a USB descriptor. Convenience functions exist to simplify * getting some types of descriptors. Use - * usb_get_device_descriptor() for USB_DT_DEVICE, + * usb_get_device_descriptor() for USB_DT_DEVICE (not exported), * and usb_get_string() or usb_string() for USB_DT_STRING. - * Configuration descriptors (USB_DT_CONFIG) are part of the device - * structure, at least for the current configuration. + * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG) + * are part of the device structure. * In addition to a number of USB-standard descriptors, some * devices also use class-specific or vendor-specific descriptors. * @@ -610,6 +610,7 @@ /** * usb_get_device_descriptor - (re)reads the device descriptor * @dev: the device whose device descriptor is being updated + * @size: how much of the descriptor to read * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, @@ -618,24 +619,35 @@ * vendors product and version fields (idVendor, idProduct, and bcdDevice). * That lets device drivers compare against non-byteswapped constants. * - * There's normally no need to use this call, although some devices - * will change their descriptors after events like updating firmware. + * Not exported, only for use by the core. If drivers really want to read + * the device descriptor directly, they can call usb_get_descriptor() with + * type = USB_DT_DEVICE and index = 0. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ -int usb_get_device_descriptor(struct usb_device *dev) +int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) { - int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, - sizeof(dev->descriptor)); + struct usb_device_descriptor *desc; + int ret; + + if (size > sizeof(*desc)) + return -EINVAL; + desc = kmalloc(sizeof(*desc), GFP_NOIO); + if (!desc) + return -ENOMEM; + + ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); if (ret >= 0) { - le16_to_cpus(&dev->descriptor.bcdUSB); - le16_to_cpus(&dev->descriptor.idVendor); - le16_to_cpus(&dev->descriptor.idProduct); - le16_to_cpus(&dev->descriptor.bcdDevice); + le16_to_cpus(&desc->bcdUSB); + le16_to_cpus(&desc->idVendor); + le16_to_cpus(&desc->idProduct); + le16_to_cpus(&desc->bcdDevice); + memcpy(&dev->descriptor, desc, size); } + kfree(desc); return ret; } @@ -1241,7 +1253,6 @@ // synchronous control message convenience routines EXPORT_SYMBOL(usb_get_descriptor); -EXPORT_SYMBOL(usb_get_device_descriptor); EXPORT_SYMBOL(usb_get_status); EXPORT_SYMBOL(usb_get_string); EXPORT_SYMBOL(usb_string); diff -urN linux-2.6.2-rc2/drivers/usb/core/usb.c linux-2.6.2-rc3/drivers/usb/core/usb.c --- linux-2.6.2-rc2/drivers/usb/core/usb.c 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/core/usb.c 2004-01-30 18:49:23.000000000 -0800 @@ -206,12 +206,15 @@ */ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) { + struct usb_host_config *config = dev->actconfig; int i; - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) - if (dev->actconfig->interface[i]->altsetting[0] + if (!config) + return NULL; + for (i = 0; i < config->desc.bNumInterfaces; i++) + if (config->interface[i]->altsetting[0] .desc.bInterfaceNumber == ifnum) - return dev->actconfig->interface[i]; + return config->interface[i]; return NULL; } @@ -233,14 +236,17 @@ struct usb_endpoint_descriptor * usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) { + struct usb_host_config *config = dev->actconfig; int i, k; - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + if (!config) + return NULL; + for (i = 0; i < config->desc.bNumInterfaces; i++) { struct usb_interface *intf; struct usb_host_interface *alt; - /* only endpoints in current altseting are active */ - intf = dev->actconfig->interface[i]; + /* only endpoints in current altsetting are active */ + intf = config->interface[i]; alt = intf->altsetting + intf->act_altsetting; for (k = 0; k < alt->desc.bNumEndpoints; k++) @@ -1059,7 +1065,7 @@ wait_ms(10); /* Let the SET_ADDRESS settle */ /* high and low speed devices don't need this... */ - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); + err = usb_get_device_descriptor(dev, 8); if (err >= 8) break; wait_ms(100); @@ -1079,8 +1085,8 @@ /* USB device state == addressed ... still not usable */ - err = usb_get_device_descriptor(dev); - if (err < (signed)sizeof(dev->descriptor)) { + err = usb_get_device_descriptor(dev, sizeof(dev->descriptor)); + if (err != (signed)sizeof(dev->descriptor)) { dev_err(&dev->dev, "device descriptor read/all, error %d\n", err); goto fail; } diff -urN linux-2.6.2-rc2/drivers/usb/core/usb.h linux-2.6.2-rc3/drivers/usb/core/usb.h --- linux-2.6.2-rc2/drivers/usb/core/usb.h 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/core/usb.h 2004-01-30 18:49:23.000000000 -0800 @@ -14,3 +14,6 @@ struct usb_endpoint_descriptor *epd); extern void usb_enable_interface (struct usb_device *dev, struct usb_interface *intf); + +extern int usb_get_device_descriptor(struct usb_device *dev, + unsigned int size); diff -urN linux-2.6.2-rc2/drivers/usb/gadget/Kconfig linux-2.6.2-rc3/drivers/usb/gadget/Kconfig --- linux-2.6.2-rc2/drivers/usb/gadget/Kconfig 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/Kconfig 2004-01-30 18:49:23.000000000 -0800 @@ -3,12 +3,10 @@ # (a) a peripheral controller, and # (b) the gadget driver using it. # -# for 2.5 kbuild, drivers/usb/gadget/Kconfig -# source this at the end of drivers/usb/Kconfig -# -menuconfig USB_GADGET +menu "USB Gadget Support" + +config USB_GADGET tristate "Support for USB Gadgets" - depends on EXPERIMENTAL help USB is a master/slave protocol, organized with one master host (such as a PC) controlling up to 127 peripheral devices. @@ -36,12 +34,15 @@ # USB Peripheral Controller Support # choice - prompt "USB Peripheral Controller Support" + prompt "USB Peripheral Controller" depends on USB_GADGET + help + A USB device uses a controller to talk to its host. + Systems should have only one such upstream link. -config USB_NET2280 - tristate "NetChip 2280 USB Peripheral Controller" - depends on PCI && USB_GADGET +config USB_GADGET_NET2280 + boolean "NetChip 2280" + depends on PCI help NetChip 2280 is a PCI based USB peripheral controller which supports both full and high speed USB 2.0 data transfers. @@ -54,21 +55,91 @@ dynamically linked module called "net2280" and force all gadget drivers to also be dynamically linked. +config USB_NET2280 + tristate + depends on USB_GADGET_NET2280 + default USB_GADGET + +config USB_GADGET_PXA2XX + boolean "PXA 2xx or IXP 42x" + depends on ARCH_PXA || ARCH_IXP425 + help + Intel's PXA 2xx series XScale ARM-5TE processors include + an integrated full speed USB 1.1 device controller. The + controller in the IXP 4xx series is register-compatible. + + It has fifteen fixed-function endpoints, as well as endpoint + zero (for control transfers). + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "pxa2xx_udc" and force all + gadget drivers to also be dynamically linked. + +config USB_PXA2XX + tristate + depends on USB_GADGET_PXA2XX + default USB_GADGET + +# if there's only one gadget driver, using only two bulk endpoints, +# don't waste memory for the other endpoints +config USB_PXA2XX_SMALL + depends on USB_GADGET_PXA2XX + bool + default y if USB_ZERO + default y if USB_ETH + default y if USB_G_SERIAL + +config USB_GADGET_GOKU + boolean "Toshiba TC86C001 'Goku-S'" + depends on PCI + help + The Toshiba TC86C001 is a PCI device which includes controllers + for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI). + + The device controller has three configurable (bulk or interrupt) + endpoints, plus endpoint zero (for control transfers). + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "goku_udc" and to force all + gadget drivers to also be dynamically linked. + +config USB_GOKU + tristate + depends on USB_GADGET_GOKU + default USB_GADGET + +# this could be built elsewhere (doesn't yet exist) +config USB_GADGET_SA1100 + boolean "SA 1100" + depends on ARCH_SA1100 + help + Intel's SA-1100 is an ARM-4 processor with an integrated + full speed USB 1.1 device controller. + + It has two fixed-function endpoints, as well as endpoint + zero (for control transfers). + +config USB_SA1100 + tristate + depends on USB_GADGET_SA1100 + default USB_GADGET + endchoice + # # USB Gadget Drivers # choice - prompt "USB Gadget Drivers" + tristate "USB Gadget Drivers" depends on USB_GADGET default USB_ETH -# FIXME want a cleaner dependency/config approach for drivers. +# this first set of drivers all depend on bulk-capable hardware. config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" - depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) + depends on EXPERIMENTAL help Gadget Zero is a two-configuration device. It either sinks and sources bulk data; or it loops back a configurable number of @@ -91,26 +162,9 @@ Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_zero". -config USB_ZERO_NET2280 - bool - # for now, treat the "dummy" hcd as if it were a net2280 - depends on USB_ZERO && (USB_NET2280 || USB_DUMMY_HCD) - default y - -config USB_ZERO_PXA2XX - bool - depends on USB_ZERO && USB_PXA2XX - default y - -config USB_ZERO_SA1100 - bool - depends on USB_ZERO && USB_SA1100 - default y - - config USB_ETH tristate "Ethernet Gadget" - depends on USB_GADGET && NET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) + depends on NET help This driver implements Ethernet style communication, in either of two ways: @@ -136,26 +190,9 @@ Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_ether". - -config USB_ETH_NET2280 - bool - # for now, treat the "dummy" hcd as if it were a net2280 - depends on USB_ETH && (USB_NET2280 || USB_DUMMY_HCD) - default y - -config USB_ETH_PXA2XX - bool - depends on USB_ETH && USB_PXA2XX - default y - -config USB_ETH_SA1100 - bool - depends on USB_ETH && USB_SA1100 - default y - config USB_GADGETFS tristate "Gadget Filesystem (EXPERIMENTAL)" - depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX) && EXPERIMENTAL + depends on EXPERIMENTAL help This driver provides a filesystem based API that lets user mode programs implement a single-configuration USB device, including @@ -166,38 +203,44 @@ Say "y" to link the driver statically, or "m" to build a dynamically linked module called "gadgetfs". -config USB_GADGETFS_NET2280 - bool - # for now, treat the "dummy" hcd as if it were a net2280 - depends on USB_GADGETFS && (USB_NET2280 || USB_DUMMY_HCD) - default y +config USB_FILE_STORAGE + tristate "File-backed Storage Gadget (DEVELOPMENT)" + # we don't support the SA1100 because of its limitations + depends on USB_GADGET_SA1100 = n + help + The File-backed Storage Gadget acts as a USB Mass Storage + disk drive. As its storage repository it can use a regular + file or a block device (in much the same way as the "loop" + device driver), specified as a module parameter. -config USB_GADGETFS_PXA2XX - bool - depends on USB_GADGETFS && USB_PXA2XX - default y + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "g_file_storage". + +config USB_FILE_STORAGE_TEST + bool "File-backed Storage Gadget test version" + depends on USB_FILE_STORAGE + default n + help + Say "y" to generate the larger testing version of the + File-backed Storage Gadget, useful for probing the + behavior of USB Mass Storage hosts. Not needed for + normal operation. config USB_G_SERIAL - tristate "serial Gadget" - depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) + tristate "Serial Gadget" + help + The Serial Gadget talks to the Linux-USB generic serial driver. -config USB_G_SERIAL_NET2280 - bool - # for now, treat the "dummy" hcd as if it were a net2280 - depends on USB_G_SERIAL && (USB_NET2280 || USB_DUMMY_HCD) - default y + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "g_serial". -config USB_G_SERIAL_PXA2XX - bool - depends on USB_G_SERIAL && USB_PXA2XX - default y -config USB_G_SERIAL_SA1100 - bool - depends on USB_G_SERIAL && USB_SA1100 - default y +# put drivers that need isochronous transfer support (for audio +# or video class gadget drivers), or specific hardware, here. + +# - none yet endchoice -# endmenuconfig +endmenu diff -urN linux-2.6.2-rc2/drivers/usb/gadget/Makefile linux-2.6.2-rc3/drivers/usb/gadget/Makefile --- linux-2.6.2-rc2/drivers/usb/gadget/Makefile 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/Makefile 2004-01-30 18:49:23.000000000 -0800 @@ -2,6 +2,8 @@ # USB peripheral controller drivers # obj-$(CONFIG_USB_NET2280) += net2280.o +obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o +obj-$(CONFIG_USB_GOKU) += goku_udc.o # # USB gadget drivers @@ -10,8 +12,11 @@ g_ether-objs := ether.o usbstring.o g_serial-objs := serial.o usbstring.o gadgetfs-objs := inode.o usbstring.o +g_file_storage-objs := file_storage.o usbstring.o obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_ETH) += g_ether.o obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o +obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o obj-$(CONFIG_USB_G_SERIAL) += g_serial.o + diff -urN linux-2.6.2-rc2/drivers/usb/gadget/ether.c linux-2.6.2-rc3/drivers/usb/gadget/ether.c --- linux-2.6.2-rc2/drivers/usb/gadget/ether.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/ether.c 2004-01-30 18:49:23.000000000 -0800 @@ -122,12 +122,9 @@ * * CHIP ... hardware identifier * DRIVER_VERSION_NUM ... alerts the host side driver to differences - * EP0_MAXPACKET ... controls packetization of control requests * EP_*_NAME ... which endpoints do we use for which purpose? * EP_*_NUM ... numbers for them (often limited by hardware) * HIGHSPEED ... define if ep0 and descriptors need high speed support - * MAX_USB_POWER ... define if we use other than 100 mA bus current - * SELFPOWER ... unless we can run on bus power, USB_CONFIG_ATT_SELFPOWER * WAKEUP ... if hardware supports remote wakeup AND we will issue the * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP * @@ -143,6 +140,9 @@ /* #undef on hardware that can't implement CDC */ #define DEV_CONFIG_CDC +/* undef on bus-powered hardware, and #define MAX_USB_POWER */ +#define SELFPOWER + /* * NetChip 2280, PCI based. * @@ -152,11 +152,10 @@ * performance note: only PIO needs per-usb-packet IRQs (ep0, ep-e, ep-f) * otherwise IRQs are per-Ethernet-packet unless TX_DELAY and chaining help. */ -#ifdef CONFIG_USB_ETH_NET2280 +#ifdef CONFIG_USB_GADGET_NET2280 #define CHIP "net2280" #define DEFAULT_QLEN 4 /* has dma chaining */ #define DRIVER_VERSION_NUM 0x0101 -#define EP0_MAXPACKET 64 static const char EP_OUT_NAME [] = "ep-a"; #define EP_OUT_NUM 1 static const char EP_IN_NAME [] = "ep-b"; @@ -164,8 +163,6 @@ static const char EP_STATUS_NAME [] = "ep-f"; #define EP_STATUS_NUM 3 #define HIGHSPEED -/* specific hardware configs could be bus-powered */ -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER /* supports remote wakeup, but this driver doesn't */ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); @@ -186,17 +183,14 @@ * multiple interfaces (or altsettings) aren't usable. so this hardware * can't implement CDC, which needs both capabilities. */ -#ifdef CONFIG_USB_ETH_PXA2XX +#ifdef CONFIG_USB_GADGET_PXA2XX #undef DEV_CONFIG_CDC #define CHIP "pxa2xx" #define DRIVER_VERSION_NUM 0x0103 -#define EP0_MAXPACKET 16 static const char EP_OUT_NAME [] = "ep2out-bulk"; #define EP_OUT_NUM 2 static const char EP_IN_NAME [] = "ep1in-bulk"; #define EP_IN_NUM 1 -/* doesn't support bus-powered operation */ -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER /* supports remote wakeup, but this driver doesn't */ /* no hw optimizations to apply */ @@ -209,17 +203,14 @@ * can't have a notification endpoint, since there are only the two * bulk-capable ones. the CDC spec allows that. */ -#ifdef CONFIG_USB_ETH_SA1100 +#ifdef CONFIG_USB_GADGET_SA1100 #define CHIP "sa1100" #define DRIVER_VERSION_NUM 0x0105 -#define EP0_MAXPACKET 8 static const char EP_OUT_NAME [] = "ep1out-bulk"; #define EP_OUT_NUM 1 static const char EP_IN_NAME [] = "ep2in-bulk"; #define EP_IN_NUM 2 // EP_STATUS_NUM is undefined -/* doesn't support bus-powered operation */ -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER /* doesn't support remote wakeup? */ /* no hw optimizations to apply */ @@ -231,25 +222,43 @@ * * This has three semi-configurable full speed bulk/interrupt endpoints. */ -#ifdef CONFIG_USB_ETH_GOKU +#ifdef CONFIG_USB_GADGET_GOKU #define CHIP "goku" #define DRIVER_VERSION_NUM 0x0106 -#define EP0_MAXPACKET 8 static const char EP_OUT_NAME [] = "ep1-bulk"; #define EP_OUT_NUM 1 static const char EP_IN_NAME [] = "ep2-bulk"; #define EP_IN_NUM 2 static const char EP_STATUS_NAME [] = "ep3-bulk"; #define EP_STATUS_NUM 3 -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER /* doesn't support remote wakeup */ #define hw_optimize(g) do {} while (0) #endif +/* + * SuperH UDC: UDC built-in to some Renesas SH processors. + * + * This has three semi-configurable full speed bulk/interrupt endpoints. + * + * Only one configuration and interface is supported. So this hardware + * can't implement CDC. + */ +#ifdef CONFIG_USB_GADGET_SUPERH +#undef DEV_CONFIG_CDC +#define CHIP "superh" +#define DRIVER_VERSION_NUM 0x0107 +static const char EP_OUT_NAME[] = "ep1out-bulk"; +#define EP_OUT_NUM 1 +static const char EP_IN_NAME[] = "ep2in-bulk"; +#define EP_IN_NUM 2 + +#define hw_optimize(g) do {} while (0) +#endif + /*-------------------------------------------------------------------------*/ -#ifndef EP0_MAXPACKET +#ifndef CHIP # error Configure some USB peripheral controller driver! #endif @@ -280,19 +289,15 @@ * hardware that supports remote wakeup defaults to disabling it. */ -#ifndef SELFPOWER -/* default: say we rely on bus power */ -#define SELFPOWER 0 -/* else: - * - SELFPOWER value must be USB_CONFIG_ATT_SELFPOWER - * - MAX_USB_POWER may be nonzero. - */ -#endif - #ifndef MAX_USB_POWER -/* any hub supports this steady state bus power consumption */ -#define MAX_USB_POWER 100 /* mA */ +#ifdef SELFPOWER +/* some hosts are confused by 0mA */ +#define MAX_USB_POWER 2 /* mA */ +#else +/* bus powered */ +#error Define your bus power consumption! #endif +#endif /* MAX_USB_POWER */ #ifndef WAKEUP /* default: this driver won't do remote wakeup */ @@ -376,7 +381,7 @@ /* * This device advertises one configuration. */ -static const struct usb_device_descriptor +static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -386,7 +391,6 @@ .bDeviceClass = DEV_CONFIG_CLASS, .bDeviceSubClass = 0, .bDeviceProtocol = 0, - .bMaxPacketSize0 = EP0_MAXPACKET, .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), @@ -396,7 +400,7 @@ .bNumConfigurations = 1, }; -static const struct usb_config_descriptor +static struct usb_config_descriptor eth_config = { .bLength = sizeof eth_config, .bDescriptorType = USB_DT_CONFIG, @@ -409,7 +413,7 @@ #endif .bConfigurationValue = DEV_CONFIG_VALUE, .iConfiguration = STRING_PRODUCT, - .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, + .bmAttributes = USB_CONFIG_ATT_ONE | WAKEUP, .bMaxPower = (MAX_USB_POWER + 1) / 2, }; @@ -645,7 +649,7 @@ .bInterval = 1, }; -static const struct usb_qualifier_descriptor +static struct usb_qualifier_descriptor dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, @@ -653,12 +657,10 @@ .bcdUSB = __constant_cpu_to_le16 (0x0200), .bDeviceClass = DEV_CONFIG_CLASS, - /* assumes ep0 uses the same value for both speeds ... */ - .bMaxPacketSize0 = EP0_MAXPACKET, - .bNumConfigurations = 1, }; + /* maxpacket and other transfer characteristics vary by speed. */ #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) @@ -959,7 +961,7 @@ if (number == dev->config) return 0; -#ifdef CONFIG_USB_ETH_SA1100 +#ifdef CONFIG_USB_GADGET_SA1100 if (dev->config && atomic_read (&dev->tx_qlen) != 0) { /* tx fifo is full, but we can't clear it...*/ INFO (dev, "can't change configurations\n"); @@ -1006,6 +1008,7 @@ /* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications */ #define CDC_NOTIFY_NETWORK_CONNECTION 0x00 /* required; 6.3.1 */ +#define CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 /* optional; 6.3.2 */ #define CDC_NOTIFY_SPEED_CHANGE 0x2a /* required; 6.3.8 */ struct cdc_notification { @@ -1123,6 +1126,8 @@ /* see section 3.8.2 table 10 of the CDC spec for more ethernet * requests, mostly for filters (multicast, pm) and statistics */ +#define CDC_SEND_ENCAPSULATED_REQUEST 0x00 /* optional */ +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 /* optional */ #define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */ /* @@ -1188,7 +1193,7 @@ value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC); spin_unlock (&dev->lock); break; -#ifdef CONFIG_USB_ETH_PXA2XX +#ifdef CONFIG_USB_GADGET_PXA2XX /* PXA UDC prevents us from using SET_INTERFACE in normal ways. * And it hides GET_CONFIGURATION and GET_INTERFACE too. */ @@ -1638,7 +1643,7 @@ req->context = skb; req->complete = tx_complete; -#ifdef CONFIG_USB_ETH_SA1100 +#ifdef CONFIG_USB_GADGET_SA1100 /* don't demand zlp (req->zero) support from all hardware */ if ((length % dev->in_ep->maxpacket) == 0) length++; @@ -1770,6 +1775,17 @@ return -ENODEV; #endif + device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; +#ifdef HIGHSPEED + /* assumes ep0 uses the same value for both speeds ... */ + dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; +#endif + +#ifdef SELFPOWERED + eth_config.bmAttributes |= USB_CONFIG_ATT_SELFPOWERED; + usb_gadget_set_selfpowered (gadget); +#endif + net = alloc_etherdev (sizeof *dev); if (!net) return status; diff -urN linux-2.6.2-rc2/drivers/usb/gadget/file_storage.c linux-2.6.2-rc3/drivers/usb/gadget/file_storage.c --- linux-2.6.2-rc2/drivers/usb/gadget/file_storage.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/file_storage.c 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,4169 @@ +/* + * file_storage.c -- File-backed USB Storage Gadget, for USB development + * + * Copyright (C) 2003 Alan Stern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * The File-backed Storage Gadget acts as a USB Mass Storage device, + * appearing to the host as a disk drive. In addition to providing an + * example of a genuinely useful gadget driver for a USB device, it also + * illustrates a technique of double-buffering for increased throughput. + * Last but not least, it gives an easy way to probe the behavior of the + * Mass Storage drivers in a USB host. + * + * Backing storage is provided by a regular file or a block device, specified + * by the "file" module parameter. Access can be limited to read-only by + * setting the optional "ro" module parameter. + * + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected + * by the optional "transport" module parameter. It also supports the + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by + * the optional "protocol" module parameter. For testing purposes the + * gadget will indicate that it has removable media if the optional + * "removable" module parameter is set. In addition, the default Vendor ID, + * Product ID, and release number can be overridden. + * + * There is support for multiple logical units (LUNs), each of which has + * its own backing file. The number of LUNs can be set using the optional + * "luns" module parameter (anywhere from 1 to 8), and the corresponding + * files are specified using comma-separated lists for "file" and "ro". + * The default number of LUNs is taken from the number of "file" elements; + * it is 1 if "file" is not given. If "removable" is not set then a backing + * file must be specified for each LUN. If it is set, then an unspecified + * or empty backing filename means the LUN's medium is not loaded. + * + * Requirements are modest; only a bulk-in and a bulk-out endpoint are + * needed (an interrupt-out endpoint is also needed for CBI). The memory + * requirement amounts to two 16K buffers, size configurable by a parameter. + * Support is included for both full-speed and high-speed operation. + * + * Module options: + * + * file=filename[,filename...] + * Required if "removable" is not set, names of + * the files or block devices used for + * backing storage + * ro=b[,b...] Default false, booleans for read-only access + * luns=N Default N = number of filenames, number of + * LUNs to support + * transport=XXX Default BBB, transport name (CB, CBI, or BBB) + * protocol=YYY Default SCSI, protocol name (RBC, 8020 or + * ATAPI, QIC, UFI, 8070, or SCSI; + * also 1 - 6) + * removable Default false, boolean for removable media + * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID + * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID + * release=0xRRRR Override the USB release number (bcdDevice) + * buflen=N Default N=16384, buffer size used (will be + * rounded down to a multiple of + * PAGE_CACHE_SIZE) + * stall Default determined according to the type of + * USB device controller (usually true), + * boolean to permit the driver to halt + * bulk endpoints + * + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file" and "ro" + * options are available; default values are used for everything else. + * + * The pathnames of the backing files and the ro settings are available in + * the attribute files "file" and "ro" in the lun subdirectory of the + * gadget's sysfs directory. If CONFIG_USB_FILE_STORAGE_TEST and the + * "removable" option are both set, writing to these files will simulate + * ejecting/loading the medium (writing an empty line means eject) and + * adjusting a write-enable tab. Changes to the ro setting are not allowed + * when the medium is loaded. + * + * This gadget driver is heavily based on "Gadget Zero" by David Brownell. + */ + + +/* + * Driver Design + * + * The FSG driver is fairly straightforward. There is a main kernel + * thread that handles most of the work. Interrupt routines field + * callbacks from the controller driver: bulk- and interrupt-request + * completion notifications, endpoint-0 events, and disconnect events. + * Completion events are passed to the main thread by wakeup calls. Many + * ep0 requests are handled at interrupt time, but SetInterface, + * SetConfiguration, and device reset requests are forwarded to the + * thread in the form of "exceptions" using SIGUSR1 signals (since they + * should interrupt any ongoing file I/O operations). + * + * The thread's main routine implements the standard command/data/status + * parts of a SCSI interaction. It and its subroutines are full of tests + * for pending signals/exceptions -- all this polling is necessary since + * the kernel has no setjmp/longjmp equivalents. (Maybe this is an + * indication that the driver really wants to be running in userspace.) + * An important point is that so long as the thread is alive it keeps an + * open reference to the backing file. This will prevent unmounting + * the backing file's underlying filesystem and could cause problems + * during system shutdown, for example. To prevent such problems, the + * thread catches INT, TERM, and KILL signals and converts them into + * an EXIT exception. + * + * In normal operation the main thread is started during the gadget's + * fsg_bind() callback and stopped during fsg_unbind(). But it can also + * exit when it receives a signal, and there's no point leaving the + * gadget running when the thread is dead. So just before the thread + * exits, it deregisters the gadget driver. This makes things a little + * tricky: The driver is deregistered at two places, and the exiting + * thread can indirectly call fsg_unbind() which in turn can tell the + * thread to exit. The first problem is resolved through the use of the + * REGISTERED atomic bitflag; the driver will only be deregistered once. + * The second problem is resolved by having fsg_unbind() check + * fsg->state; it won't try to stop the thread if the state is already + * FSG_STATE_TERMINATED. + * + * To provide maximum throughput, the driver uses a circular pipeline of + * buffer heads (struct fsg_buffhd). In principle the pipeline can be + * arbitrarily long; in practice the benefits don't justify having more + * than 2 stages (i.e., double buffering). But it helps to think of the + * pipeline as being a long one. Each buffer head contains a bulk-in and + * a bulk-out request pointer (since the buffer can be used for both + * output and input -- directions always are given from the host's + * point of view) as well as a pointer to the buffer and various state + * variables. + * + * Use of the pipeline follows a simple protocol. There is a variable + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. + * At any time that buffer head may still be in use from an earlier + * request, so each buffer head has a state variable indicating whether + * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the + * buffer head to be EMPTY, filling the buffer either by file I/O or by + * USB I/O (during which the buffer head is BUSY), and marking the buffer + * head FULL when the I/O is complete. Then the buffer will be emptied + * (again possibly by USB I/O, during which it is marked BUSY) and + * finally marked EMPTY again (possibly by a completion routine). + * + * A module parameter tells the driver to avoid stalling the bulk + * endpoints wherever the transport specification allows. This is + * necessary for some UDCs like the SuperH, which cannot reliably clear a + * halt on a bulk endpoint. However, under certain circumstances the + * Bulk-only specification requires a stall. In such cases the driver + * will halt the endpoint and set a flag indicating that it should clear + * the halt in software during the next device reset. Hopefully this + * will permit everything to work correctly. + * + * One subtle point concerns sending status-stage responses for ep0 + * requests. Some of these requests, such as device reset, can involve + * interrupting an ongoing file I/O operation, which might take an + * arbitrarily long time. During that delay the host might give up on + * the original ep0 request and issue a new one. When that happens the + * driver should not notify the host about completion of the original + * request, as the host will no longer be waiting for it. So the driver + * assigns to each ep0 request a unique tag, and it keeps track of the + * tag value of the request associated with a long-running exception + * (device-reset, interface-change, or configuration-change). When the + * exception handler is finished, the status-stage response is submitted + * only if the current ep0 request tag is equal to the exception request + * tag. Thus only the most recently received ep0 request will get a + * status-stage response. + * + * Warning: This driver source file is too long. It ought to be split up + * into a header file plus about 3 separate .c files, to handle the details + * of the Gadget, USB Mass Storage, and SCSI protocols. + */ + + +#undef DEBUG +#undef VERBOSE +#undef DUMP_MSGS + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/*-------------------------------------------------------------------------*/ + +#define DRIVER_DESC "File-backed Storage Gadget" +#define DRIVER_NAME "g_file_storage" +#define DRIVER_VERSION "14 January 2004" + +static const char longname[] = DRIVER_DESC; +static const char shortname[] = DRIVER_NAME; + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("Dual BSD/GPL"); + +/* Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. */ +#define DRIVER_VENDOR_ID 0x0525 // NetChip +#define DRIVER_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget + + +/*-------------------------------------------------------------------------*/ + +/* + * Hardware-specific configuration, controlled by which device + * controller driver was configured. + * + * CHIP ... hardware identifier + * DRIVER_VERSION_NUM ... alerts the host side driver to differences + * EP_*_NAME ... which endpoints do we use for which purpose? + * EP_*_NUM ... numbers for them (often limited by hardware) + * FS_BULK_IN_MAXPACKET ... maxpacket value for full-speed bulk-in ep + * FS_BULK_OUT_MAXPACKET ... maxpacket value for full-speed bulk-out ep + * HIGHSPEED ... define if ep0 and descriptors need high speed support + * MAX_USB_POWER ... define if we use other than 100 mA bus current + * SELFPOWER ... if we can run on bus power, zero + * NO_BULK_STALL ... bulk endpoint halts don't work well so avoid them + */ + + +/* + * NetChip 2280, PCI based. + * + * This has half a dozen configurable endpoints, four with dedicated + * DMA channels to manage their FIFOs. It supports high speed. + * Those endpoints can be arranged in any desired configuration. + */ +#ifdef CONFIG_USB_GADGET_NET2280 +#define CHIP "net2280" +#define DRIVER_VERSION_NUM 0x0201 +static const char EP_BULK_IN_NAME[] = "ep-a"; +#define EP_BULK_IN_NUM 1 +#define FS_BULK_IN_MAXPACKET 64 +static const char EP_BULK_OUT_NAME[] = "ep-b"; +#define EP_BULK_OUT_NUM 2 +#define FS_BULK_OUT_MAXPACKET 64 +static const char EP_INTR_IN_NAME[] = "ep-e"; +#define EP_INTR_IN_NUM 5 +#define HIGHSPEED +#endif + + +/* + * Dummy_hcd, software-based loopback controller. + * + * This imitates the abilities of the NetChip 2280, so we will use + * the same configuration. + */ +#ifdef CONFIG_USB_GADGET_DUMMY_HCD +#define CHIP "dummy" +#define DRIVER_VERSION_NUM 0x0202 +static const char EP_BULK_IN_NAME[] = "ep-a"; +#define EP_BULK_IN_NUM 1 +#define FS_BULK_IN_MAXPACKET 64 +static const char EP_BULK_OUT_NAME[] = "ep-b"; +#define EP_BULK_OUT_NUM 2 +#define FS_BULK_OUT_MAXPACKET 64 +static const char EP_INTR_IN_NAME[] = "ep-e"; +#define EP_INTR_IN_NUM 5 +#define HIGHSPEED +#endif + + +/* + * PXA-2xx UDC: widely used in second gen Linux-capable PDAs. + * + * This has fifteen fixed-function full speed endpoints, and it + * can support all USB transfer types. + * + * These supports three or four configurations, with fixed numbers. + * The hardware interprets SET_INTERFACE, net effect is that you + * can't use altsettings or reset the interfaces independently. + * So stick to a single interface. + */ +#ifdef CONFIG_USB_GADGET_PXA2XX +#define CHIP "pxa2xx" +#define DRIVER_VERSION_NUM 0x0203 +static const char EP_BULK_IN_NAME[] = "ep1in-bulk"; +#define EP_BULK_IN_NUM 1 +#define FS_BULK_IN_MAXPACKET 64 +static const char EP_BULK_OUT_NAME[] = "ep2out-bulk"; +#define EP_BULK_OUT_NUM 2 +#define FS_BULK_OUT_MAXPACKET 64 +static const char EP_INTR_IN_NAME[] = "ep6in-bulk"; +#define EP_INTR_IN_NUM 6 +#endif + + +/* + * SuperH UDC: UDC built-in to some Renesas SH processors. + * + * This has three fixed-function full speed bulk/interrupt endpoints. + * + * Only one configuration and interface is supported (SET_CONFIGURATION + * and SET_INTERFACE are handled completely by the hardware). + */ +#ifdef CONFIG_USB_GADGET_SUPERH +#define CHIP "superh" +#define DRIVER_VERSION_NUM 0x0205 +static const char EP_BULK_IN_NAME[] = "ep2in-bulk"; +#define EP_BULK_IN_NUM 2 +#define FS_BULK_IN_MAXPACKET 64 +static const char EP_BULK_OUT_NAME[] = "ep1out-bulk"; +#define EP_BULK_OUT_NUM 1 +#define FS_BULK_OUT_MAXPACKET 64 +static const char EP_INTR_IN_NAME[] = "ep3in-bulk"; +#define EP_INTR_IN_NUM 3 +#define NO_BULK_STALL +#endif + + +/* + * Toshiba TC86C001 ("Goku-S") UDC + * + * This has three semi-configurable full speed bulk/interrupt endpoints. + */ +#ifdef CONFIG_USB_GADGET_GOKU +#define CHIP "goku" +#define DRIVER_VERSION_NUM 0x0206 +static const char EP_BULK_OUT_NAME [] = "ep1-bulk"; +#define EP_BULK_OUT_NUM 1 +#define FS_BULK_IN_MAXPACKET 64 +static const char EP_BULK_IN_NAME [] = "ep2-bulk"; +#define EP_BULK_IN_NUM 2 +#define FS_BULK_OUT_MAXPACKET 64 +static const char EP_INTR_IN_NAME [] = "ep3-bulk"; +#define EP_INTR_IN_NUM 3 +#endif + + +/*-------------------------------------------------------------------------*/ + +#ifndef CHIP +# error Configure some USB peripheral controller driver! +#endif + +/* Power usage is config specific. + * Hardware that supports remote wakeup defaults to disabling it. + */ +#ifndef SELFPOWER +/* default: say we're self-powered */ +#define SELFPOWER USB_CONFIG_ATT_SELFPOWER +/* else: + * - SELFPOWER value must be zero + * - MAX_USB_POWER may be nonzero. + */ +#endif + +#ifndef MAX_USB_POWER +/* Any hub supports this steady state bus power consumption */ +#define MAX_USB_POWER 100 /* mA */ +#endif + +/* We don't support remote wake-up */ + +#ifdef NO_BULK_STALL +#define CAN_STALL 0 +#else +#define CAN_STALL 1 +#endif + + +/*-------------------------------------------------------------------------*/ + +#define xprintk(f,level,fmt,args...) \ + dev_printk(level , &(f)->gadget->dev , fmt , ## args) +#define yprintk(l,level,fmt,args...) \ + dev_printk(level , &(l)->dev , fmt , ## args) + +#ifdef DEBUG +#define DBG(fsg,fmt,args...) \ + xprintk(fsg , KERN_DEBUG , fmt , ## args) +#define LDBG(lun,fmt,args...) \ + yprintk(lun , KERN_DEBUG , fmt , ## args) +#define MDBG(fmt,args...) \ + printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args) +#else +#define DBG(fsg,fmt,args...) \ + do { } while (0) +#define LDBG(lun,fmt,args...) \ + do { } while (0) +#define MDBG(fmt,args...) \ + do { } while (0) +#undef VERBOSE +#undef DUMP_MSGS +#endif /* DEBUG */ + +#ifdef VERBOSE +#define VDBG DBG +#define VLDBG LDBG +#else +#define VDBG(fsg,fmt,args...) \ + do { } while (0) +#define VLDBG(lun,fmt,args...) \ + do { } while (0) +#endif /* VERBOSE */ + +#define ERROR(fsg,fmt,args...) \ + xprintk(fsg , KERN_ERR , fmt , ## args) +#define LERROR(lun,fmt,args...) \ + yprintk(lun , KERN_ERR , fmt , ## args) + +#define WARN(fsg,fmt,args...) \ + xprintk(fsg , KERN_WARNING , fmt , ## args) +#define LWARN(lun,fmt,args...) \ + yprintk(lun , KERN_WARNING , fmt , ## args) + +#define INFO(fsg,fmt,args...) \ + xprintk(fsg , KERN_INFO , fmt , ## args) +#define LINFO(lun,fmt,args...) \ + yprintk(lun , KERN_INFO , fmt , ## args) + +#define MINFO(fmt,args...) \ + printk(KERN_INFO DRIVER_NAME ": " fmt, ## args) + + +/*-------------------------------------------------------------------------*/ + +/* Encapsulate the module parameter settings */ + +#define MAX_LUNS 8 + + /* Arggh! There should be a module_param_array_named macro! */ +static char *file[MAX_LUNS] = {NULL, }; +static int ro[MAX_LUNS] = {0, }; + +static struct { + int num_filenames; + int num_ros; + unsigned int nluns; + + char *transport_parm; + char *protocol_parm; + int removable; + unsigned short vendor; + unsigned short product; + unsigned short release; + unsigned int buflen; + int can_stall; + + int transport_type; + char *transport_name; + int protocol_type; + char *protocol_name; + +} mod_data = { // Default values + .transport_parm = "BBB", + .protocol_parm = "SCSI", + .removable = 0, + .vendor = DRIVER_VENDOR_ID, + .product = DRIVER_PRODUCT_ID, + .release = DRIVER_VERSION_NUM, + .buflen = 16384, + .can_stall = CAN_STALL, + }; + + +module_param_array(file, charp, mod_data.num_filenames, S_IRUGO); +MODULE_PARM_DESC(file, "names of backing files or devices"); + +module_param_array(ro, bool, mod_data.num_ros, S_IRUGO); +MODULE_PARM_DESC(ro, "true to force read-only"); + + +/* In the non-TEST version, only the file and ro module parameters + * are available. */ +#ifdef CONFIG_USB_FILE_STORAGE_TEST + +module_param_named(luns, mod_data.nluns, uint, S_IRUGO); +MODULE_PARM_DESC(luns, "number of LUNs"); + +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO); +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)"); + +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO); +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " + "8070, or SCSI)"); + +module_param_named(removable, mod_data.removable, bool, S_IRUGO); +MODULE_PARM_DESC(removable, "true to simulate removable media"); + +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO); +MODULE_PARM_DESC(vendor, "USB Vendor ID"); + +module_param_named(product, mod_data.product, ushort, S_IRUGO); +MODULE_PARM_DESC(product, "USB Product ID"); + +module_param_named(release, mod_data.release, ushort, S_IRUGO); +MODULE_PARM_DESC(release, "USB release number"); + +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); +MODULE_PARM_DESC(buflen, "I/O buffer size"); + +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); +MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); + +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ + + +/*-------------------------------------------------------------------------*/ + +/* USB protocol value = the transport method */ +#define USB_PR_CBI 0x00 // Control/Bulk/Interrupt +#define USB_PR_CB 0x01 // Control/Bulk w/o interrupt +#define USB_PR_BULK 0x50 // Bulk-only + +/* USB subclass value = the protocol encapsulation */ +#define USB_SC_RBC 0x01 // Reduced Block Commands (flash) +#define USB_SC_8020 0x02 // SFF-8020i, MMC-2, ATAPI (CD-ROM) +#define USB_SC_QIC 0x03 // QIC-157 (tape) +#define USB_SC_UFI 0x04 // UFI (floppy) +#define USB_SC_8070 0x05 // SFF-8070i (removable) +#define USB_SC_SCSI 0x06 // Transparent SCSI + +/* Bulk-only data structures */ + +/* Command Block Wrapper */ +struct bulk_cb_wrap { + u32 Signature; // Contains 'USBC' + u32 Tag; // Unique per command id + u32 DataTransferLength; // Size of the data + u8 Flags; // Direction in bit 7 + u8 Lun; // LUN (normally 0) + u8 Length; // Of the CDB, <= MAX_COMMAND_SIZE + u8 CDB[16]; // Command Data Block +}; + +#define USB_BULK_CB_WRAP_LEN 31 +#define USB_BULK_CB_SIG 0x43425355 // Spells out USBC +#define USB_BULK_IN_FLAG 0x80 + +/* Command Status Wrapper */ +struct bulk_cs_wrap { + u32 Signature; // Should = 'USBS' + u32 Tag; // Same as original command + u32 Residue; // Amount not transferred + u8 Status; // See below +}; + +#define USB_BULK_CS_WRAP_LEN 13 +#define USB_BULK_CS_SIG 0x53425355 // Spells out 'USBS' +#define USB_STATUS_PASS 0 +#define USB_STATUS_FAIL 1 +#define USB_STATUS_PHASE_ERROR 2 + +/* Bulk-only class specific requests */ +#define USB_BULK_RESET_REQUEST 0xff +#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe + + +/* CBI Interrupt data structure */ +struct interrupt_data { + u8 bType; + u8 bValue; +}; + +#define CBI_INTERRUPT_DATA_LEN 2 + +/* CBI Accept Device-Specific Command request */ +#define USB_CBI_ADSC_REQUEST 0x00 + + +#define MAX_COMMAND_SIZE 16 // Length of a SCSI Command Data Block + +/* SCSI commands that we recognize */ +#define SC_FORMAT_UNIT 0x04 +#define SC_INQUIRY 0x12 +#define SC_MODE_SELECT_6 0x15 +#define SC_MODE_SELECT_10 0x55 +#define SC_MODE_SENSE_6 0x1a +#define SC_MODE_SENSE_10 0x5a +#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define SC_READ_6 0x08 +#define SC_READ_10 0x28 +#define SC_READ_12 0xa8 +#define SC_READ_CAPACITY 0x25 +#define SC_READ_FORMAT_CAPACITIES 0x23 +#define SC_RELEASE 0x17 +#define SC_REQUEST_SENSE 0x03 +#define SC_RESERVE 0x16 +#define SC_SEND_DIAGNOSTIC 0x1d +#define SC_START_STOP_UNIT 0x1b +#define SC_SYNCHRONIZE_CACHE 0x35 +#define SC_TEST_UNIT_READY 0x00 +#define SC_VERIFY 0x2f +#define SC_WRITE_6 0x0a +#define SC_WRITE_10 0x2a +#define SC_WRITE_12 0xaa + +/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ +#define SS_NO_SENSE 0 +#define SS_COMMUNICATION_FAILURE 0x040800 +#define SS_INVALID_COMMAND 0x052000 +#define SS_INVALID_FIELD_IN_CDB 0x052400 +#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 +#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 +#define SS_MEDIUM_NOT_PRESENT 0x023a00 +#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 +#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 +#define SS_RESET_OCCURRED 0x062900 +#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 +#define SS_UNRECOVERED_READ_ERROR 0x031100 +#define SS_WRITE_ERROR 0x030c02 +#define SS_WRITE_PROTECTED 0x072700 + +#define SK(x) ((u8) ((x) >> 16)) // Sense Key byte, etc. +#define ASC(x) ((u8) ((x) >> 8)) +#define ASCQ(x) ((u8) (x)) + + +/*-------------------------------------------------------------------------*/ + +/* + * These definitions will permit the compiler to avoid generating code for + * parts of the driver that aren't used in the non-TEST version. Even gcc + * can recognize when a test of a constant expression yields a dead code + * path. + * + * Also, in the non-TEST version, open_backing_file() is only used during + * initialization and the sysfs attribute store_xxx routines aren't used + * at all. We will define NORMALLY_INIT to mark them as __init so they + * don't occupy kernel code space unnecessarily. + */ + +#ifdef CONFIG_USB_FILE_STORAGE_TEST + +#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK) +#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI) +#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI) +#define backing_file_is_open(curlun) ((curlun)->filp != NULL) +#define NORMALLY_INIT + +#else + +#define transport_is_bbb() 1 +#define transport_is_cbi() 0 +#define protocol_is_scsi() 1 +#define backing_file_is_open(curlun) 1 +#define NORMALLY_INIT __init + +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ + + +struct lun { + struct file *filp; + loff_t file_length; + loff_t num_sectors; + + unsigned int ro : 1; + unsigned int prevent_medium_removal : 1; + unsigned int registered : 1; + + u32 sense_data; + u32 sense_data_info; + u32 unit_attention_data; + + struct device dev; +}; + +static inline struct lun *dev_to_lun(struct device *dev) +{ + return container_of(dev, struct lun, dev); +} + + +/* Big enough to hold our biggest descriptor */ +#define EP0_BUFSIZE 256 +#define DELAYED_STATUS (EP0_BUFSIZE + 999) // An impossibly large value + +/* Number of buffers we will use. 2 is enough for double-buffering */ +#define NUM_BUFFERS 2 + +enum fsg_buffer_state { + BUF_STATE_EMPTY = 0, + BUF_STATE_FULL, + BUF_STATE_BUSY +}; + +struct fsg_buffhd { + void *buf; + dma_addr_t dma; + volatile enum fsg_buffer_state state; + struct fsg_buffhd *next; + + /* The NetChip 2280 is faster, and handles some protocol faults + * better, if we don't submit any short bulk-out read requests. + * So we will record the intended request length here. */ + unsigned int bulk_out_intended_length; + + struct usb_request *inreq; + volatile int inreq_busy; + struct usb_request *outreq; + volatile int outreq_busy; +}; + +enum fsg_state { + FSG_STATE_COMMAND_PHASE = -10, // This one isn't used anywhere + FSG_STATE_DATA_PHASE, + FSG_STATE_STATUS_PHASE, + + FSG_STATE_IDLE = 0, + FSG_STATE_ABORT_BULK_OUT, + FSG_STATE_RESET, + FSG_STATE_INTERFACE_CHANGE, + FSG_STATE_CONFIG_CHANGE, + FSG_STATE_DISCONNECT, + FSG_STATE_EXIT, + FSG_STATE_TERMINATED +}; + +enum data_direction { + DATA_DIR_UNKNOWN = 0, + DATA_DIR_FROM_HOST, + DATA_DIR_TO_HOST, + DATA_DIR_NONE +}; + +struct fsg_dev { + /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ + spinlock_t lock; + struct usb_gadget *gadget; + + /* filesem protects: backing files in use */ + struct rw_semaphore filesem; + + struct usb_ep *ep0; // Handy copy of gadget->ep0 + struct usb_request *ep0req; // For control responses + volatile unsigned int ep0_req_tag; + const char *ep0req_name; + + struct usb_request *intreq; // For interrupt responses + volatile int intreq_busy; + struct fsg_buffhd *intr_buffhd; + + unsigned int bulk_out_maxpacket; + enum fsg_state state; // For exception handling + unsigned int exception_req_tag; + + u8 config, new_config; + + unsigned int running : 1; + unsigned int bulk_in_enabled : 1; + unsigned int bulk_out_enabled : 1; + unsigned int intr_in_enabled : 1; + unsigned int phase_error : 1; + unsigned int short_packet_received : 1; + unsigned int bad_lun_okay : 1; + + unsigned long atomic_bitflags; +#define REGISTERED 0 +#define CLEAR_BULK_HALTS 1 + + struct usb_ep *bulk_in; + struct usb_ep *bulk_out; + struct usb_ep *intr_in; + + struct fsg_buffhd *next_buffhd_to_fill; + struct fsg_buffhd *next_buffhd_to_drain; + struct fsg_buffhd buffhds[NUM_BUFFERS]; + + wait_queue_head_t thread_wqh; + int thread_wakeup_needed; + struct completion thread_notifier; + int thread_pid; + struct task_struct *thread_task; + sigset_t thread_signal_mask; + + int cmnd_size; + u8 cmnd[MAX_COMMAND_SIZE]; + enum data_direction data_dir; + u32 data_size; + u32 data_size_from_cmnd; + u32 tag; + unsigned int lun; + u32 residue; + u32 usb_amount_left; + + /* The CB protocol offers no way for a host to know when a command + * has completed. As a result the next command may arrive early, + * and we will still have to handle it. For that reason we need + * a buffer to store new commands when using CB (or CBI, which + * does not oblige a host to wait for command completion either). */ + int cbbuf_cmnd_size; + u8 cbbuf_cmnd[MAX_COMMAND_SIZE]; + + unsigned int nluns; + struct lun *luns; + struct lun *curlun; +}; + +typedef void (*fsg_routine_t)(struct fsg_dev *); + +static int inline exception_in_progress(struct fsg_dev *fsg) +{ + return (fsg->state > FSG_STATE_IDLE); +} + +/* Make bulk-out requests be divisible by the maxpacket size */ +static void inline set_bulk_out_req_length(struct fsg_dev *fsg, + struct fsg_buffhd *bh, unsigned int length) +{ + unsigned int rem; + + bh->bulk_out_intended_length = length; + rem = length % fsg->bulk_out_maxpacket; + if (rem > 0) + length += fsg->bulk_out_maxpacket - rem; + bh->outreq->length = length; +} + +static struct fsg_dev *the_fsg; +static struct usb_gadget_driver fsg_driver; + +static void close_backing_file(struct lun *curlun); +static void close_all_backing_files(struct fsg_dev *fsg); + + +/*-------------------------------------------------------------------------*/ + +#ifdef DUMP_MSGS + +static void dump_msg(struct fsg_dev *fsg, const char *label, + const u8 *buf, unsigned int length) +{ + unsigned int start, num, i; + char line[52], *p; + + if (length >= 512) + return; + DBG(fsg, "%s, length %u:\n", label, length); + + start = 0; + while (length > 0) { + num = min(length, 16u); + p = line; + for (i = 0; i < num; ++i) { + if (i == 8) + *p++ = ' '; + sprintf(p, " %02x", buf[i]); + p += 3; + } + *p = 0; + printk(KERN_DEBUG "%6x: %s\n", start, line); + buf += num; + start += num; + length -= num; + } +} + +static void inline dump_cdb(struct fsg_dev *fsg) +{} + +#else + +static void inline dump_msg(struct fsg_dev *fsg, const char *label, + const u8 *buf, unsigned int length) +{} + +static void inline dump_cdb(struct fsg_dev *fsg) +{ + int i; + char cmdbuf[3*MAX_COMMAND_SIZE + 1]; + + for (i = 0; i < fsg->cmnd_size; ++i) + sprintf(cmdbuf + i*3, " %02x", fsg->cmnd[i]); + VDBG(fsg, "SCSI CDB: %s\n", cmdbuf); +} + +#endif /* DUMP_MSGS */ + + +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) +{ + const char *name; + + if (ep == fsg->bulk_in) + name = "bulk-in"; + else if (ep == fsg->bulk_out) + name = "bulk-out"; + else + name = ep->name; + DBG(fsg, "%s set halt\n", name); + return usb_ep_set_halt(ep); +} + + +/*-------------------------------------------------------------------------*/ + +/* Routines for unaligned data access */ + +static u16 inline get_be16(u8 *buf) +{ + return ((u16) buf[0] << 8) | ((u16) buf[1]); +} + +static u32 inline get_be32(u8 *buf) +{ + return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) | + ((u32) buf[2] << 8) | ((u32) buf[3]); +} + +static void inline put_be16(u8 *buf, u16 val) +{ + buf[0] = val >> 8; + buf[1] = val; +} + +static void inline put_be32(u8 *buf, u32 val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; +} + + +/*-------------------------------------------------------------------------*/ + +/* + * DESCRIPTORS ... most are static, but strings and (full) configuration + * descriptors are built on demand. Also the (static) config and interface + * descriptors are adjusted during fsg_bind(). + */ +#define STRING_MANUFACTURER 1 +#define STRING_PRODUCT 2 +#define STRING_SERIAL 3 + +/* There is only one configuration. */ +#define CONFIG_VALUE 1 + +static struct usb_device_descriptor +device_desc = { + .bLength = sizeof device_desc, + .bDescriptorType = USB_DT_DEVICE, + + .bcdUSB = __constant_cpu_to_le16(0x0200), + .bDeviceClass = USB_CLASS_PER_INTERFACE, + + /* The next three values can be overridden by module parameters */ + .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID), + .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID), + .bcdDevice = __constant_cpu_to_le16(DRIVER_VERSION_NUM), + + .iManufacturer = STRING_MANUFACTURER, + .iProduct = STRING_PRODUCT, + .iSerialNumber = STRING_SERIAL, + .bNumConfigurations = 1, +}; + +static struct usb_config_descriptor +config_desc = { + .bLength = sizeof config_desc, + .bDescriptorType = USB_DT_CONFIG, + + /* wTotalLength adjusted during bind() */ + .bNumInterfaces = 1, + .bConfigurationValue = CONFIG_VALUE, + .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER, + .bMaxPower = (MAX_USB_POWER + 1) / 2, +}; + +/* There is only one interface. */ + +static struct usb_interface_descriptor +intf_desc = { + .bLength = sizeof intf_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, // Adjusted during bind() + .bInterfaceClass = USB_CLASS_MASS_STORAGE, + .bInterfaceSubClass = USB_SC_SCSI, // Adjusted during bind() + .bInterfaceProtocol = USB_PR_BULK, // Adjusted during bind() +}; + +/* Three full-speed endpoint descriptors: bulk-in, bulk-out, + * and interrupt-in. */ + +static const struct usb_endpoint_descriptor +fs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = EP_BULK_IN_NUM | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(FS_BULK_IN_MAXPACKET), +}; + +static const struct usb_endpoint_descriptor +fs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = EP_BULK_OUT_NUM, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(FS_BULK_OUT_MAXPACKET), +}; + +static const struct usb_endpoint_descriptor +fs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = EP_INTR_IN_NUM | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(2), + .bInterval = 32, // frames -> 32 ms +}; + +#ifdef HIGHSPEED + +/* + * USB 2.0 devices need to expose both high speed and full speed + * descriptors, unless they only run at full speed. + * + * That means alternate endpoint descriptors (bigger packets) + * and a "device qualifier" ... plus more construction options + * for the config descriptor. + */ +static const struct usb_endpoint_descriptor +hs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = EP_BULK_IN_NUM | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), +}; + +static const struct usb_endpoint_descriptor +hs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = EP_BULK_OUT_NUM, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), + .bInterval = 1, // NAK every 1 uframe +}; + +static const struct usb_endpoint_descriptor +hs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = EP_INTR_IN_NUM | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(2), + .bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms +}; + +static struct usb_qualifier_descriptor +dev_qualifier = { + .bLength = sizeof dev_qualifier, + .bDescriptorType = USB_DT_DEVICE_QUALIFIER, + + .bcdUSB = __constant_cpu_to_le16(0x0200), + .bDeviceClass = USB_CLASS_PER_INTERFACE, + + .bNumConfigurations = 1, +}; + +/* Maxpacket and other transfer characteristics vary by speed. */ +#define ep_desc(g,fs,hs) (((g)->speed==USB_SPEED_HIGH) ? (hs) : (fs)) + +#else + +/* If there's no high speed support, maxpacket doesn't change. */ +#define ep_desc(g,fs,hs) fs + +#endif /* !HIGHSPEED */ + + +/* The CBI specification limits the serial string to 12 uppercase hexadecimal + * characters. */ +static char serial[13]; + +/* Static strings, in ISO 8859/1 */ +static struct usb_string strings[] = { + { STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, }, + { STRING_PRODUCT, longname, }, + { STRING_SERIAL, serial, }, + { } // end of list +}; + +static struct usb_gadget_strings stringtab = { + .language = 0x0409, // en-us + .strings = strings, +}; + + +/* + * Config descriptors are handcrafted. They must agree with the code + * that sets configurations and with code managing interfaces and their + * altsettings. They must also handle different speeds and other-speed + * requests. + */ +static int populate_config_buf(enum usb_device_speed speed, + u8 *buf0, u8 type, unsigned index) +{ + u8 *buf = buf0; +#ifdef HIGHSPEED + int hs; +#endif + + if (index > 0) + return -EINVAL; + if (config_desc.wTotalLength > EP0_BUFSIZE) + return -EDOM; + + /* Config (or other speed config) */ + memcpy(buf, &config_desc, USB_DT_CONFIG_SIZE); + buf[1] = type; + buf += USB_DT_CONFIG_SIZE; + + /* Interface */ + memcpy(buf, &intf_desc, USB_DT_INTERFACE_SIZE); + buf += USB_DT_INTERFACE_SIZE; + + /* The endpoints in the interface (at that speed) */ +#ifdef HIGHSPEED + hs = (speed == USB_SPEED_HIGH); + if (type == USB_DT_OTHER_SPEED_CONFIG) + hs = !hs; + if (hs) { + memcpy(buf, &hs_bulk_in_desc, USB_DT_ENDPOINT_SIZE); + buf += USB_DT_ENDPOINT_SIZE; + memcpy(buf, &hs_bulk_out_desc, USB_DT_ENDPOINT_SIZE); + buf += USB_DT_ENDPOINT_SIZE; + if (transport_is_cbi()) { + memcpy(buf, &hs_intr_in_desc, USB_DT_ENDPOINT_SIZE); + buf += USB_DT_ENDPOINT_SIZE; + } + } else +#endif + { + memcpy(buf, &fs_bulk_in_desc, USB_DT_ENDPOINT_SIZE); + buf += USB_DT_ENDPOINT_SIZE; + memcpy(buf, &fs_bulk_out_desc, USB_DT_ENDPOINT_SIZE); + buf += USB_DT_ENDPOINT_SIZE; + if (transport_is_cbi()) { + memcpy(buf, &fs_intr_in_desc, USB_DT_ENDPOINT_SIZE); + buf += USB_DT_ENDPOINT_SIZE; + } + } + + return buf - buf0; +} + + +/*-------------------------------------------------------------------------*/ + +/* These routines may be called in process context or in_irq */ + +static void wakeup_thread(struct fsg_dev *fsg) +{ + /* Tell the main thread that something has happened */ + fsg->thread_wakeup_needed = 1; + wake_up_all(&fsg->thread_wqh); +} + + +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) +{ + unsigned long flags; + struct task_struct *thread_task; + + /* Do nothing if a higher-priority exception is already in progress. + * If a lower-or-equal priority exception is in progress, preempt it + * and notify the main thread by sending it a signal. */ + spin_lock_irqsave(&fsg->lock, flags); + if (fsg->state <= new_state) { + fsg->exception_req_tag = fsg->ep0_req_tag; + fsg->state = new_state; + thread_task = fsg->thread_task; + if (thread_task) + send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task); + } + spin_unlock_irqrestore(&fsg->lock, flags); +} + + +/*-------------------------------------------------------------------------*/ + +/* The disconnect callback and ep0 routines. These always run in_irq, + * except that ep0_queue() is called in the main thread to acknowledge + * completion of various requests: set config, set interface, and + * Bulk-only device reset. */ + +static void fsg_disconnect(struct usb_gadget *gadget) +{ + struct fsg_dev *fsg = get_gadget_data(gadget); + + DBG(fsg, "disconnect or port reset\n"); + raise_exception(fsg, FSG_STATE_DISCONNECT); +} + + +static int ep0_queue(struct fsg_dev *fsg) +{ + int rc; + + rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC); + if (rc != 0 && rc != -ESHUTDOWN) { + + /* We can't do much more than wait for a reset */ + WARN(fsg, "error in submission: %s --> %d\n", + fsg->ep0->name, rc); + } + return rc; +} + +static void ep0_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + + if (req->actual > 0) + dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); + if (req->status || req->actual != req->length) + DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, + req->status, req->actual, req->length); + if (req->status == -ECONNRESET) // Request was cancelled + usb_ep_fifo_flush(ep); + + if (req->status == 0 && req->context) + ((fsg_routine_t) (req->context))(fsg); +} + + +/*-------------------------------------------------------------------------*/ + +/* Bulk and interrupt endpoint completion handlers. + * These always run in_irq. */ + +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; + + if (req->status || req->actual != req->length) + DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, + req->status, req->actual, req->length); + if (req->status == -ECONNRESET) // Request was cancelled + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + spin_lock(&fsg->lock); + bh->inreq_busy = 0; + bh->state = BUF_STATE_EMPTY; + spin_unlock(&fsg->lock); + wakeup_thread(fsg); +} + +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; + + dump_msg(fsg, "bulk-out", req->buf, req->actual); + if (req->status || req->actual != bh->bulk_out_intended_length) + DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, + req->status, req->actual, + bh->bulk_out_intended_length); + if (req->status == -ECONNRESET) // Request was cancelled + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + spin_lock(&fsg->lock); + bh->outreq_busy = 0; + bh->state = BUF_STATE_FULL; + spin_unlock(&fsg->lock); + wakeup_thread(fsg); +} + +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) +{ +#ifdef CONFIG_USB_FILE_STORAGE_TEST + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; + + if (req->status || req->actual != req->length) + DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, + req->status, req->actual, req->length); + if (req->status == -ECONNRESET) // Request was cancelled + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + spin_lock(&fsg->lock); + fsg->intreq_busy = 0; + bh->state = BUF_STATE_EMPTY; + spin_unlock(&fsg->lock); + wakeup_thread(fsg); +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ +} + + +/*-------------------------------------------------------------------------*/ + +/* Ep0 class-specific handlers. These always run in_irq. */ + +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ +#ifdef CONFIG_USB_FILE_STORAGE_TEST + struct usb_request *req = fsg->ep0req; + static u8 cbi_reset_cmnd[6] = { + SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; + + /* Error in command transfer? */ + if (req->status || req->length != req->actual || + req->actual < 6 || req->actual > MAX_COMMAND_SIZE) { + + /* Not all controllers allow a protocol stall after + * receiving control-out data, but we'll try anyway. */ + fsg_set_halt(fsg, fsg->ep0); + return; // Wait for reset + } + + /* Is it the special reset command? */ + if (req->actual >= sizeof cbi_reset_cmnd && + memcmp(req->buf, cbi_reset_cmnd, + sizeof cbi_reset_cmnd) == 0) { + + /* Raise an exception to stop the current operation + * and reinitialize our state. */ + DBG(fsg, "cbi reset request\n"); + raise_exception(fsg, FSG_STATE_RESET); + return; + } + + VDBG(fsg, "CB[I] accept device-specific command\n"); + spin_lock(&fsg->lock); + + /* Save the command for later */ + if (fsg->cbbuf_cmnd_size) + WARN(fsg, "CB[I] overwriting previous command\n"); + fsg->cbbuf_cmnd_size = req->actual; + memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); + + spin_unlock(&fsg->lock); + wakeup_thread(fsg); +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ +} + + +static int class_setup_req(struct fsg_dev *fsg, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_request *req = fsg->ep0req; + int value = -EOPNOTSUPP; + + if (!fsg->config) + return value; + + /* Handle Bulk-only class-specific requests */ + if (transport_is_bbb()) { + switch (ctrl->bRequest) { + + case USB_BULK_RESET_REQUEST: + if (ctrl->bRequestType != (USB_DIR_OUT | + USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (ctrl->wIndex != 0) { + value = -EDOM; + break; + } + + /* Raise an exception to stop the current operation + * and reinitialize our state. */ + DBG(fsg, "bulk reset request\n"); + raise_exception(fsg, FSG_STATE_RESET); + value = DELAYED_STATUS; + break; + + case USB_BULK_GET_MAX_LUN_REQUEST: + if (ctrl->bRequestType != (USB_DIR_IN | + USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (ctrl->wIndex != 0) { + value = -EDOM; + break; + } + VDBG(fsg, "get max LUN\n"); + *(u8 *) req->buf = fsg->nluns - 1; + value = min(ctrl->wLength, (u16) 1); + break; + } + } + + /* Handle CBI class-specific requests */ + else { + switch (ctrl->bRequest) { + + case USB_CBI_ADSC_REQUEST: + if (ctrl->bRequestType != (USB_DIR_OUT | + USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (ctrl->wIndex != 0) { + value = -EDOM; + break; + } + if (ctrl->wLength > MAX_COMMAND_SIZE) { + value = -EOVERFLOW; + break; + } + value = ctrl->wLength; + fsg->ep0req->context = received_cbi_adsc; + break; + } + } + + if (value == -EOPNOTSUPP) + VDBG(fsg, + "unknown class-specific control req " + "%02x.%02x v%04x i%04x l%u\n", + ctrl->bRequestType, ctrl->bRequest, + ctrl->wValue, ctrl->wIndex, ctrl->wLength); + return value; +} + + +/*-------------------------------------------------------------------------*/ + +/* Ep0 standard request handlers. These always run in_irq. */ + +static int standard_setup_req(struct fsg_dev *fsg, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_request *req = fsg->ep0req; + int value = -EOPNOTSUPP; + + /* Usually this just stores reply data in the pre-allocated ep0 buffer, + * but config change events will also reconfigure hardware. */ + switch (ctrl->bRequest) { + + case USB_REQ_GET_DESCRIPTOR: + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | + USB_RECIP_DEVICE)) + break; + switch (ctrl->wValue >> 8) { + + case USB_DT_DEVICE: + VDBG(fsg, "get device descriptor\n"); + value = min(ctrl->wLength, (u16) sizeof device_desc); + memcpy(req->buf, &device_desc, value); + break; +#ifdef HIGHSPEED + case USB_DT_DEVICE_QUALIFIER: + VDBG(fsg, "get device qualifier\n"); + value = min(ctrl->wLength, (u16) sizeof dev_qualifier); + memcpy(req->buf, &dev_qualifier, value); + break; + + case USB_DT_OTHER_SPEED_CONFIG: + VDBG(fsg, "get other-speed config descriptor\n"); + goto get_config; +#endif /* HIGHSPEED */ + case USB_DT_CONFIG: + VDBG(fsg, "get configuration descriptor\n"); +#ifdef HIGHSPEED + get_config: +#endif /* HIGHSPEED */ + value = populate_config_buf(fsg->gadget->speed, + req->buf, + ctrl->wValue >> 8, + ctrl->wValue & 0xff); + if (value >= 0) + value = min(ctrl->wLength, (u16) value); + break; + + case USB_DT_STRING: + VDBG(fsg, "get string descriptor\n"); + + /* wIndex == language code */ + value = usb_gadget_get_string(&stringtab, + ctrl->wValue & 0xff, req->buf); + if (value >= 0) + value = min(ctrl->wLength, (u16) value); + break; + } + break; + + /* One config, two speeds */ + case USB_REQ_SET_CONFIGURATION: + if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | + USB_RECIP_DEVICE)) + break; + VDBG(fsg, "set configuration\n"); + if (ctrl->wValue == CONFIG_VALUE || ctrl->wValue == 0) { + fsg->new_config = ctrl->wValue; + + /* Raise an exception to wipe out previous transaction + * state (queued bufs, etc) and set the new config. */ + raise_exception(fsg, FSG_STATE_CONFIG_CHANGE); + value = DELAYED_STATUS; + } + break; + case USB_REQ_GET_CONFIGURATION: + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | + USB_RECIP_DEVICE)) + break; + VDBG(fsg, "get configuration\n"); + *(u8 *) req->buf = fsg->config; + value = min(ctrl->wLength, (u16) 1); + break; + + case USB_REQ_SET_INTERFACE: + if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD | + USB_RECIP_INTERFACE)) + break; + if (fsg->config && ctrl->wIndex == 0) { + + /* Raise an exception to wipe out previous transaction + * state (queued bufs, etc) and install the new + * interface altsetting. */ + raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE); + value = DELAYED_STATUS; + } + break; + case USB_REQ_GET_INTERFACE: + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | + USB_RECIP_INTERFACE)) + break; + if (!fsg->config) + break; + if (ctrl->wIndex != 0) { + value = -EDOM; + break; + } + VDBG(fsg, "get interface\n"); + *(u8 *) req->buf = 0; + value = min(ctrl->wLength, (u16) 1); + break; + + default: + VDBG(fsg, + "unknown control req %02x.%02x v%04x i%04x l%u\n", + ctrl->bRequestType, ctrl->bRequest, + ctrl->wValue, ctrl->wIndex, ctrl->wLength); + } + + return value; +} + + +static int fsg_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + struct fsg_dev *fsg = get_gadget_data(gadget); + int rc; + + ++fsg->ep0_req_tag; // Record arrival of a new request + fsg->ep0req->context = NULL; + fsg->ep0req->length = 0; + dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); + + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) + rc = class_setup_req(fsg, ctrl); + else + rc = standard_setup_req(fsg, ctrl); + + /* Respond with data/status or defer until later? */ + if (rc >= 0 && rc != DELAYED_STATUS) { + fsg->ep0req->length = rc; + fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? + "ep0-in" : "ep0-out"); + rc = ep0_queue(fsg); + } + + /* Device either stalls (rc < 0) or reports success */ + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +/* All the following routines run in process context */ + + +/* Use this for bulk or interrupt transfers, not ep0 */ +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, + struct usb_request *req, volatile int *pbusy, + volatile enum fsg_buffer_state *state) +{ + int rc; + + if (ep == fsg->bulk_in) + dump_msg(fsg, "bulk-in", req->buf, req->length); + else if (ep == fsg->intr_in) + dump_msg(fsg, "intr-in", req->buf, req->length); + *pbusy = 1; + *state = BUF_STATE_BUSY; + rc = usb_ep_queue(ep, req, GFP_KERNEL); + if (rc != 0) { + *pbusy = 0; + *state = BUF_STATE_EMPTY; + + /* We can't do much more than wait for a reset */ + + /* Note: currently the net2280 driver fails zero-length + * submissions if DMA is enabled. */ + if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && + req->length == 0)) + WARN(fsg, "error in submission: %s --> %d\n", + ep->name, rc); + } +} + + +static int sleep_thread(struct fsg_dev *fsg) +{ + int rc; + + /* Wait until a signal arrives or we are woken up */ + rc = wait_event_interruptible(fsg->thread_wqh, + fsg->thread_wakeup_needed); + fsg->thread_wakeup_needed = 0; + return (rc ? -EINTR : 0); +} + + +/*-------------------------------------------------------------------------*/ + +static int do_read(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + u32 lba; + struct fsg_buffhd *bh; + int rc; + u32 amount_left; + loff_t file_offset, file_offset_tmp; + unsigned int amount; + unsigned int partial_page; + ssize_t nread; + + /* Get the starting Logical Block Address and check that it's + * not too big */ + if (fsg->cmnd[0] == SC_READ_6) + lba = (fsg->cmnd[1] << 16) | get_be16(&fsg->cmnd[2]); + else { + lba = get_be32(&fsg->cmnd[2]); + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = don't read from the + * cache), but we don't implement them. */ + if ((fsg->cmnd[1] & ~0x18) != 0) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + file_offset = ((loff_t) lba) << 9; + + /* Carry out the file reads */ + amount_left = fsg->data_size_from_cmnd; + if (unlikely(amount_left == 0)) + return -EIO; // No default reply + + for (;;) { + + /* Figure out how much we need to read: + * Try to read the remaining amount. + * But don't read more than the buffer size. + * And don't try to read past the end of the file. + * Finally, if we're not at a page boundary, don't read past + * the next page. + * If this means reading 0 then we were asked to read past + * the end of file. */ + amount = min((unsigned int) amount_left, mod_data.buflen); + amount = min((loff_t) amount, + curlun->file_length - file_offset); + partial_page = file_offset & (PAGE_CACHE_SIZE - 1); + if (partial_page > 0) + amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - + partial_page); + + /* Wait for the next buffer to become available */ + bh = fsg->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + + /* If we were asked to read past the end of file, + * end with an empty buffer. */ + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = file_offset >> 9; + bh->inreq->length = 0; + bh->state = BUF_STATE_FULL; + break; + } + + /* Perform the read */ + file_offset_tmp = file_offset; + nread = vfs_read(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + if (signal_pending(current)) + return -EINTR; + + if (nread < 0) { + LDBG(curlun, "error in file read: %d\n", + (int) nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file read: %d/%u\n", + (int) nread, amount); + nread -= (nread & 511); // Round down to a block + } + file_offset += nread; + amount_left -= nread; + fsg->residue -= nread; + bh->inreq->length = nread; + bh->state = BUF_STATE_FULL; + + /* If an error occurred, report it and its position */ + if (nread < amount) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->sense_data_info = file_offset >> 9; + break; + } + + if (amount_left == 0) + break; // No more left to read + + /* Send this buffer and go read some more */ + bh->inreq->zero = 0; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + } + + return -EIO; // No default reply +} + + +/*-------------------------------------------------------------------------*/ + +static int do_write(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + u32 lba; + struct fsg_buffhd *bh; + int get_some_more; + u32 amount_left_to_req, amount_left_to_write; + loff_t usb_offset, file_offset, file_offset_tmp; + unsigned int amount; + unsigned int partial_page; + ssize_t nwritten; + int rc; + + if (curlun->ro) { + curlun->sense_data = SS_WRITE_PROTECTED; + return -EINVAL; + } + curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait + + /* Get the starting Logical Block Address and check that it's + * not too big */ + if (fsg->cmnd[0] == SC_WRITE_6) + lba = (fsg->cmnd[1] << 16) | get_be16(&fsg->cmnd[2]); + else { + lba = get_be32(&fsg->cmnd[2]); + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = write directly to the + * medium). We don't implement DPO; we implement FUA by + * performing synchronous output. */ + if ((fsg->cmnd[1] & ~0x18) != 0) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + if (fsg->cmnd[1] & 0x08) // FUA + curlun->filp->f_flags |= O_SYNC; + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* Carry out the file writes */ + get_some_more = 1; + file_offset = usb_offset = ((loff_t) lba) << 9; + amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; + + while (amount_left_to_write > 0) { + + /* Queue a request for more data from the host */ + bh = fsg->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY && get_some_more) { + + /* Figure out how much we want to get: + * Try to get the remaining amount. + * But don't get more than the buffer size. + * And don't try to go past the end of the file. + * If we're not at a page boundary, + * don't go past the next page. + * If this means getting 0, then we were asked + * to write past the end of file. + * Finally, round down to a block boundary. */ + amount = min(amount_left_to_req, mod_data.buflen); + amount = min((loff_t) amount, curlun->file_length - + usb_offset); + partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); + if (partial_page > 0) + amount = min(amount, + (unsigned int) PAGE_CACHE_SIZE - partial_page); + + if (amount == 0) { + get_some_more = 0; + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = usb_offset >> 9; + continue; + } + amount -= (amount & 511); + if (amount == 0) { + + /* Why were we were asked to transfer a + * partial block? */ + get_some_more = 0; + continue; + } + + /* Get the next buffer */ + usb_offset += amount; + fsg->usb_amount_left -= amount; + amount_left_to_req -= amount; + if (amount_left_to_req == 0) + get_some_more = 0; + + /* amount is always divisible by 512, hence by + * the bulk-out maxpacket size */ + bh->outreq->length = bh->bulk_out_intended_length = + amount; + start_transfer(fsg, fsg->bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + continue; + } + + /* Write the received data to the backing file */ + bh = fsg->next_buffhd_to_drain; + if (bh->state == BUF_STATE_EMPTY && !get_some_more) + break; // We stopped early + if (bh->state == BUF_STATE_FULL) { + fsg->next_buffhd_to_drain = bh->next; + bh->state = BUF_STATE_EMPTY; + + /* Did something go wrong with the transfer? */ + if (bh->outreq->status != 0) { + curlun->sense_data = SS_COMMUNICATION_FAILURE; + curlun->sense_data_info = file_offset >> 9; + break; + } + + amount = bh->outreq->actual; + if (curlun->file_length - file_offset < amount) { + LERROR(curlun, + "write %u @ %llu beyond end %llu\n", + amount, (unsigned long long) file_offset, + (unsigned long long) curlun->file_length); + amount = curlun->file_length - file_offset; + } + + /* Perform the write */ + file_offset_tmp = file_offset; + nwritten = vfs_write(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nwritten); + if (signal_pending(current)) + return -EINTR; // Interrupted! + + if (nwritten < 0) { + LDBG(curlun, "error in file write: %d\n", + (int) nwritten); + nwritten = 0; + } else if (nwritten < amount) { + LDBG(curlun, "partial file write: %d/%u\n", + (int) nwritten, amount); + nwritten -= (nwritten & 511); + // Round down to a block + } + file_offset += nwritten; + amount_left_to_write -= nwritten; + fsg->residue -= nwritten; + + /* If an error occurred, report it and its position */ + if (nwritten < amount) { + curlun->sense_data = SS_WRITE_ERROR; + curlun->sense_data_info = file_offset >> 9; + break; + } + + /* Did the host decide to stop early? */ + if (bh->outreq->actual != bh->outreq->length) { + fsg->short_packet_received = 1; + break; + } + continue; + } + + /* Wait for something to happen */ + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + + return -EIO; // No default reply +} + + +/*-------------------------------------------------------------------------*/ + +/* Sync the file data, don't bother with the metadata. + * This code was copied from fs/buffer.c:sys_fdatasync(). */ +static int fsync_sub(struct lun *curlun) +{ + struct file *filp = curlun->filp; + struct inode *inode; + int rc, err; + + if (curlun->ro || !filp) + return 0; + if (!filp->f_op->fsync) + return -EINVAL; + + inode = filp->f_dentry->d_inode; + down(&inode->i_sem); + current->flags |= PF_SYNCWRITE; + rc = filemap_fdatawrite(inode->i_mapping); + err = filp->f_op->fsync(filp, filp->f_dentry, 1); + if (!rc) + rc = err; + err = filemap_fdatawait(inode->i_mapping); + if (!rc) + rc = err; + current->flags &= ~PF_SYNCWRITE; + up(&inode->i_sem); + VLDBG(curlun, "fdatasync -> %d\n", rc); + return rc; +} + +static void fsync_all(struct fsg_dev *fsg) +{ + int i; + + for (i = 0; i < fsg->nluns; ++i) + fsync_sub(&fsg->luns[i]); +} + +static int do_synchronize_cache(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + int rc; + + /* We ignore the requested LBA and write out all file's + * dirty data buffers. */ + rc = fsync_sub(curlun); + if (rc) + curlun->sense_data = SS_WRITE_ERROR; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static void invalidate_sub(struct lun *curlun) +{ + struct file *filp = curlun->filp; + struct inode *inode = filp->f_dentry->d_inode; + unsigned long rc; + + rc = invalidate_inode_pages(inode->i_mapping); + VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc); +} + +static int do_verify(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + u32 lba; + u32 verification_length; + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; + loff_t file_offset, file_offset_tmp; + u32 amount_left; + unsigned int amount; + ssize_t nread; + + /* Get the starting Logical Block Address and check that it's + * not too big */ + lba = get_be32(&fsg->cmnd[2]); + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) but we don't implement it. */ + if ((fsg->cmnd[1] & ~0x10) != 0) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + verification_length = get_be16(&fsg->cmnd[7]); + if (unlikely(verification_length == 0)) + return -EIO; // No default reply + + /* Prepare to carry out the file verify */ + amount_left = verification_length << 9; + file_offset = ((loff_t) lba) << 9; + + /* Write out all the dirty buffers before invalidating them */ + fsync_sub(curlun); + if (signal_pending(current)) + return -EINTR; + + invalidate_sub(curlun); + if (signal_pending(current)) + return -EINTR; + + /* Just try to read the requested blocks */ + while (amount_left > 0) { + + /* Figure out how much we need to read: + * Try to read the remaining amount, but not more than + * the buffer size. + * And don't try to read past the end of the file. + * If this means reading 0 then we were asked to read + * past the end of file. */ + amount = min((unsigned int) amount_left, mod_data.buflen); + amount = min((loff_t) amount, + curlun->file_length - file_offset); + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = file_offset >> 9; + break; + } + + /* Perform the read */ + file_offset_tmp = file_offset; + nread = vfs_read(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + if (signal_pending(current)) + return -EINTR; + + if (nread < 0) { + LDBG(curlun, "error in file verify: %d\n", + (int) nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file verify: %d/%u\n", + (int) nread, amount); + nread -= (nread & 511); // Round down to a sector + } + if (nread == 0) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->sense_data_info = file_offset >> 9; + break; + } + file_offset += nread; + amount_left -= nread; + } + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + u8 *buf = (u8 *) bh->buf; + + static char vendor_id[] = "Linux "; + static char product_id[] = "File-Stor Gadget"; + + if (!fsg->curlun) { // Unsupported LUNs are okay + fsg->bad_lun_okay = 1; + memset(buf, 0, 36); + buf[0] = 0x7f; // Unsupported, no device-type + return 36; + } + + memset(buf, 0, 8); // Non-removable, direct-access device + if (mod_data.removable) + buf[1] = 0x80; + buf[2] = 2; // ANSI SCSI level 2 + buf[3] = 2; // SCSI-2 INQUIRY data format + buf[4] = 31; // Additional length + // No special options + sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id, + DRIVER_VERSION_NUM); + return 36; +} + + +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct lun *curlun = fsg->curlun; + u8 *buf = (u8 *) bh->buf; + u32 sd, sdinfo; + + /* + * From the SCSI-2 spec., section 7.9 (Unit attention condition): + * + * If a REQUEST SENSE command is received from an initiator + * with a pending unit attention condition (before the target + * generates the contingent allegiance condition), then the + * target shall either: + * a) report any pending sense data and preserve the unit + * attention condition on the logical unit, or, + * b) report the unit attention condition, may discard any + * pending sense data, and clear the unit attention + * condition on the logical unit for that initiator. + * + * FSG normally uses option a); enable this code to use option b). + */ +#if 0 + if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + } +#endif + + if (!curlun) { // Unsupported LUNs are okay + fsg->bad_lun_okay = 1; + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + sdinfo = 0; + } else { + sd = curlun->sense_data; + sdinfo = curlun->sense_data_info; + curlun->sense_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + } + + memset(buf, 0, 18); + buf[0] = 0x80 | 0x70; // Valid, current error + buf[2] = SK(sd); + put_be32(&buf[3], sdinfo); // Sense information + buf[7] = 18 - 7; // Additional sense length + buf[12] = ASC(sd); + buf[13] = ASCQ(sd); + return 18; +} + + +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct lun *curlun = fsg->curlun; + u32 lba = get_be32(&fsg->cmnd[2]); + int pmi = fsg->cmnd[8]; + u8 *buf = (u8 *) bh->buf; + + /* Check the PMI and LBA fields */ + if (pmi > 1 || (pmi == 0 && lba != 0)) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + put_be32(&buf[0], curlun->num_sectors - 1); // Max logical block + put_be32(&buf[4], 512); // Block length + return 8; +} + + +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct lun *curlun = fsg->curlun; + int mscmnd = fsg->cmnd[0]; + u8 *buf = (u8 *) bh->buf; + u8 *buf0 = buf; + int pc, page_code; + int changeable_values, all_pages; + int valid_page = 0; + int len, limit; + + if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + pc = fsg->cmnd[2] >> 6; + page_code = fsg->cmnd[2] & 0x3f; + if (pc == 3) { + curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; + return -EINVAL; + } + changeable_values = (pc == 1); + all_pages = (page_code == 0x3f); + + /* Write the mode parameter header. Fixed values are: default + * medium type, no cache control (DPOFUA), and no block descriptors. + * The only variable value is the WriteProtect bit. We will fill in + * the mode data length later. */ + memset(buf, 0, 8); + if (mscmnd == SC_MODE_SENSE_6) { + buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA + buf += 4; + limit = 255; + } else { // SC_MODE_SENSE_10 + buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA + buf += 8; + limit = 65535; // Should really be mod_data.buflen + } + + /* No block descriptors */ + + /* The mode pages, in numerical order. The only page we support + * is the Caching page. */ + if (page_code == 0x08 || all_pages) { + valid_page = 1; + buf[0] = 0x08; // Page code + buf[1] = 10; // Page length + memset(buf+2, 0, 10); // None of the fields are changeable + + if (!changeable_values) { + buf[2] = 0x04; // Write cache enable, + // Read cache not disabled + // No cache retention priorities + put_be16(&buf[4], 0xffff); // Don't disable prefetch + // Minimum prefetch = 0 + put_be16(&buf[8], 0xffff); // Maximum prefetch + put_be16(&buf[10], 0xffff); // Maximum prefetch ceiling + } + buf += 12; + } + + /* Check that a valid page was requested and the mode data length + * isn't too long. */ + len = buf - buf0; + if (!valid_page || len > limit) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + /* Store the mode data length */ + if (mscmnd == SC_MODE_SENSE_6) + buf0[0] = len - 1; + else + put_be16(buf0, len - 2); + return len; +} + + +static int do_start_stop(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + int loej, start; + + if (!mod_data.removable) { + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + + // int immed = fsg->cmnd[1] & 0x01; + loej = fsg->cmnd[4] & 0x02; + start = fsg->cmnd[4] & 0x01; + +#ifdef CONFIG_USB_FILE_STORAGE_TEST + if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed + (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + if (!start) { + + /* Are we allowed to unload the media? */ + if (curlun->prevent_medium_removal) { + LDBG(curlun, "unload attempt prevented\n"); + curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; + return -EINVAL; + } + if (loej) { // Simulate an unload/eject + up_read(&fsg->filesem); + down_write(&fsg->filesem); + close_backing_file(curlun); + up_write(&fsg->filesem); + down_read(&fsg->filesem); + } + } else { + + /* Our emulation doesn't support mounting; the medium is + * available for use as soon as it is loaded. */ + if (!backing_file_is_open(curlun)) { + curlun->sense_data = SS_MEDIUM_NOT_PRESENT; + return -EINVAL; + } + } +#endif + return 0; +} + + +static int do_prevent_allow(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + int prevent; + + if (!mod_data.removable) { + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + + prevent = fsg->cmnd[4] & 0x01; + if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + if (curlun->prevent_medium_removal && !prevent) + fsync_sub(curlun); + curlun->prevent_medium_removal = prevent; + return 0; +} + + +static int do_read_format_capacities(struct fsg_dev *fsg, + struct fsg_buffhd *bh) +{ + struct lun *curlun = fsg->curlun; + u8 *buf = (u8 *) bh->buf; + + buf[0] = buf[1] = buf[2] = 0; + buf[3] = 8; // Only the Current/Maximum Capacity Descriptor + buf += 4; + + put_be32(&buf[0], curlun->num_sectors); // Number of blocks + put_be32(&buf[4], 512); // Block length + buf[4] = 0x02; // Current capacity + return 12; +} + + +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct lun *curlun = fsg->curlun; + + /* We don't support MODE SELECT */ + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; +} + + +/*-------------------------------------------------------------------------*/ + +static int halt_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + rc = fsg_set_halt(fsg, fsg->bulk_in); + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint halt\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARN(fsg, "usb_ep_set_halt -> %d\n", rc); + rc = 0; + break; + } + + /* Wait for a short time and then try again */ + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(HZ / 10) != 0) + return -EINTR; + rc = usb_ep_set_halt(fsg->bulk_in); + } + return rc; +} + +static int pad_with_zeros(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; + u32 nkeep = bh->inreq->length; + u32 nsend; + int rc; + + bh->state = BUF_STATE_EMPTY; // For the first iteration + fsg->usb_amount_left = nkeep + fsg->residue; + while (fsg->usb_amount_left > 0) { + + /* Wait for the next buffer to be free */ + while (bh->state != BUF_STATE_EMPTY) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + + nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen); + memset(bh->buf + nkeep, 0, nsend - nkeep); + bh->inreq->length = nsend; + bh->inreq->zero = 0; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + bh = fsg->next_buffhd_to_fill = bh->next; + fsg->usb_amount_left -= nsend; + nkeep = 0; + } + return 0; +} + +static int throw_away_data(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh; + u32 amount; + int rc; + + while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY || + fsg->usb_amount_left > 0) { + + /* Throw away the data in a filled buffer */ + if (bh->state == BUF_STATE_FULL) { + bh->state = BUF_STATE_EMPTY; + fsg->next_buffhd_to_drain = bh->next; + + /* A short packet or an error ends everything */ + if (bh->outreq->actual != bh->outreq->length || + bh->outreq->status != 0) { + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); + return -EINTR; + } + continue; + } + + /* Try to submit another request if we need one */ + bh = fsg->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) { + amount = min(fsg->usb_amount_left, + (u32) mod_data.buflen); + + /* amount is always divisible by 512, hence by + * the bulk-out maxpacket size */ + bh->outreq->length = bh->bulk_out_intended_length = + amount; + start_transfer(fsg, fsg->bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + fsg->usb_amount_left -= amount; + continue; + } + + /* Otherwise wait for something to happen */ + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + return 0; +} + + +static int finish_reply(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; + int rc = 0; + + switch (fsg->data_dir) { + case DATA_DIR_NONE: + break; // Nothing to send + + /* If we don't know whether the host wants to read or write, + * this must be CB or CBI with an unknown command. We mustn't + * try to send or receive any data. So stall both bulk pipes + * if we can and wait for a reset. */ + case DATA_DIR_UNKNOWN: + if (mod_data.can_stall) { + fsg_set_halt(fsg, fsg->bulk_out); + rc = halt_bulk_in_endpoint(fsg); + } + break; + + /* All but the last buffer of data must have already been sent */ + case DATA_DIR_TO_HOST: + if (fsg->data_size == 0) + ; // Nothing to send + + /* If there's no residue, simply send the last buffer */ + else if (fsg->residue == 0) { + bh->inreq->zero = 0; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + } + + /* There is a residue. For CB and CBI, simply mark the end + * of the data with a short packet. However, if we are + * allowed to stall, there was no data at all (residue == + * data_size), and the command failed (invalid LUN or + * sense data is set), then halt the bulk-in endpoint + * instead. */ + else if (!transport_is_bbb()) { + if (mod_data.can_stall && + fsg->residue == fsg->data_size && + (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) { + bh->state = BUF_STATE_EMPTY; + rc = halt_bulk_in_endpoint(fsg); + } else { + bh->inreq->zero = 1; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + } + } + + /* For Bulk-only, if we're allowed to stall then send the + * short packet and halt the bulk-in endpoint. If we can't + * stall, pad out the remaining data with 0's. */ + else { + if (mod_data.can_stall) { + bh->inreq->zero = 1; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + rc = halt_bulk_in_endpoint(fsg); + } else + rc = pad_with_zeros(fsg); + } + break; + + /* We have processed all we want from the data the host has sent. + * There may still be outstanding bulk-out requests. */ + case DATA_DIR_FROM_HOST: + if (fsg->residue == 0) + ; // Nothing to receive + + /* Did the host stop sending unexpectedly early? */ + else if (fsg->short_packet_received) { + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; + } + + /* We haven't processed all the incoming data. If we are + * allowed to stall, halt the bulk-out endpoint and cancel + * any outstanding requests. */ + else if (mod_data.can_stall) { + fsg_set_halt(fsg, fsg->bulk_out); + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; + } + + /* We can't stall. Read in the excess data and throw it + * all away. */ + else + rc = throw_away_data(fsg); + break; + } + return rc; +} + + +static int send_status(struct fsg_dev *fsg) +{ + struct lun *curlun = fsg->curlun; + struct fsg_buffhd *bh; + int rc; + u8 status = USB_STATUS_PASS; + u32 sd, sdinfo = 0; + + /* Wait for the next buffer to become available */ + bh = fsg->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + + if (curlun) { + sd = curlun->sense_data; + sdinfo = curlun->sense_data_info; + } else if (fsg->bad_lun_okay) + sd = SS_NO_SENSE; + else + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + + if (fsg->phase_error) { + DBG(fsg, "sending phase-error status\n"); + status = USB_STATUS_PHASE_ERROR; + sd = SS_INVALID_COMMAND; + } else if (sd != SS_NO_SENSE) { + DBG(fsg, "sending command-failure status\n"); + status = USB_STATUS_FAIL; + VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" + " info x%x\n", + SK(sd), ASC(sd), ASCQ(sd), sdinfo); + } + + if (transport_is_bbb()) { + struct bulk_cs_wrap *csw = (struct bulk_cs_wrap *) bh->buf; + + /* Store and send the Bulk-only CSW */ + csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); + csw->Tag = fsg->tag; + csw->Residue = fsg->residue; + csw->Status = status; + + bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->zero = 0; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + + } else if (mod_data.transport_type == USB_PR_CB) { + + /* Control-Bulk transport has no status stage! */ + return 0; + + } else { // USB_PR_CBI + struct interrupt_data *buf = (struct interrupt_data *) + bh->buf; + + /* Store and send the Interrupt data. UFI sends the ASC + * and ASCQ bytes. Everything else sends a Type (which + * is always 0) and the status Value. */ + if (mod_data.protocol_type == USB_SC_UFI) { + buf->bType = ASC(sd); + buf->bValue = ASCQ(sd); + } else { + buf->bType = 0; + buf->bValue = status; + } + fsg->intreq->length = CBI_INTERRUPT_DATA_LEN; + + fsg->intr_buffhd = bh; // Point to the right buffhd + fsg->intreq->buf = bh->inreq->buf; + fsg->intreq->dma = bh->inreq->dma; + fsg->intreq->context = bh; + start_transfer(fsg, fsg->intr_in, fsg->intreq, + &fsg->intreq_busy, &bh->state); + } + + fsg->next_buffhd_to_fill = bh->next; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* Check whether the command is properly formed and whether its data size + * and direction agree with the values we already have. */ +static int check_command(struct fsg_dev *fsg, int cmnd_size, + enum data_direction data_dir, unsigned int mask, + int needs_medium, const char *name) +{ + int i; + int lun = fsg->cmnd[1] >> 5; + static const char dirletter[4] = {'u', 'o', 'i', 'n'}; + char hdlen[20]; + struct lun *curlun; + + /* Adjust the expected cmnd_size for protocol encapsulation padding. + * Transparent SCSI doesn't pad. */ + if (protocol_is_scsi()) + ; + + /* There's some disagreement as to whether RBC pads commands or not. + * We'll play it safe and accept either form. */ + else if (mod_data.protocol_type == USB_SC_RBC) { + if (fsg->cmnd_size == 12) + cmnd_size = 12; + + /* All the other protocols pad to 12 bytes */ + } else + cmnd_size = 12; + + hdlen[0] = 0; + if (fsg->data_dir != DATA_DIR_UNKNOWN) + sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir], + fsg->data_size); + VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", + name, cmnd_size, dirletter[(int) data_dir], + fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen); + + /* We can't reply at all until we know the correct data direction + * and size. */ + if (fsg->data_size_from_cmnd == 0) + data_dir = DATA_DIR_NONE; + if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI + fsg->data_dir = data_dir; + fsg->data_size = fsg->data_size_from_cmnd; + + } else { // Bulk-only + if (fsg->data_size < fsg->data_size_from_cmnd) { + + /* Host data size < Device data size is a phase error. + * Carry out the command, but only transfer as much + * as we are allowed. */ + fsg->data_size_from_cmnd = fsg->data_size; + fsg->phase_error = 1; + } + } + fsg->residue = fsg->usb_amount_left = fsg->data_size; + + /* Conflicting data directions is a phase error */ + if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) + goto phase_error; + + /* Verify the length of the command itself */ + if (cmnd_size != fsg->cmnd_size) { + + /* Special case workaround: MS-Windows issues REQUEST SENSE + * with cbw->Length == 12 (it should be 6). */ + if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12) + cmnd_size = fsg->cmnd_size; + else + goto phase_error; + } + + /* Check that the LUN values are oonsistent */ + if (transport_is_bbb()) { + if (fsg->lun != lun) + DBG(fsg, "using LUN %d from CBW, " + "not LUN %d from CDB\n", + fsg->lun, lun); + } else + fsg->lun = lun; // Use LUN from the command + + /* Check the LUN */ + if (fsg->lun >= 0 && fsg->lun < fsg->nluns) { + fsg->curlun = curlun = &fsg->luns[fsg->lun]; + if (fsg->cmnd[0] != SC_REQUEST_SENSE) { + curlun->sense_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + } + } else { + fsg->curlun = curlun = NULL; + fsg->bad_lun_okay = 0; + + /* INQUIRY and REQUEST SENSE commands are explicitly allowed + * to use unsupported LUNs; all others may not. */ + if (fsg->cmnd[0] != SC_INQUIRY && + fsg->cmnd[0] != SC_REQUEST_SENSE) { + DBG(fsg, "unsupported LUN %d\n", fsg->lun); + return -EINVAL; + } + } + + /* If a unit attention condition exists, only INQUIRY and + * REQUEST SENSE commands are allowed; anything else must fail. */ + if (curlun && curlun->unit_attention_data != SS_NO_SENSE && + fsg->cmnd[0] != SC_INQUIRY && + fsg->cmnd[0] != SC_REQUEST_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + return -EINVAL; + } + + /* Check that only command bytes listed in the mask are non-zero */ + fsg->cmnd[1] &= 0x1f; // Mask away the LUN + for (i = 1; i < cmnd_size; ++i) { + if (fsg->cmnd[i] && !(mask & (1 << i))) { + if (curlun) + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + + /* If the medium isn't mounted and the command needs to access + * it, return an error. */ + if (curlun && !backing_file_is_open(curlun) && needs_medium) { + curlun->sense_data = SS_MEDIUM_NOT_PRESENT; + return -EINVAL; + } + + return 0; + +phase_error: + fsg->phase_error = 1; + return -EINVAL; +} + + +static int do_scsi_command(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh; + int rc; + int reply = -EINVAL; + int i; + static char unknown[16]; + + dump_cdb(fsg); + + /* Wait for the next buffer to become available for data or status */ + bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + fsg->phase_error = 0; + fsg->short_packet_received = 0; + + down_read(&fsg->filesem); // We're using the backing file + switch (fsg->cmnd[0]) { + + case SC_INQUIRY: + fsg->data_size_from_cmnd = fsg->cmnd[4]; + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "INQUIRY")) == 0) + reply = do_inquiry(fsg, bh); + break; + + case SC_MODE_SELECT_6: + fsg->data_size_from_cmnd = fsg->cmnd[4]; + if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, + (1<<1) | (1<<4), 0, + "MODE SELECT(6)")) == 0) + reply = do_mode_select(fsg, bh); + break; + + case SC_MODE_SELECT_10: + fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); + if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, + (1<<1) | (3<<7), 0, + "MODE SELECT(10)")) == 0) + reply = do_mode_select(fsg, bh); + break; + + case SC_MODE_SENSE_6: + fsg->data_size_from_cmnd = fsg->cmnd[4]; + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (1<<4), 0, + "MODE SENSE(6)")) == 0) + reply = do_mode_sense(fsg, bh); + break; + + case SC_MODE_SENSE_10: + fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (3<<7), 0, + "MODE SENSE(10)")) == 0) + reply = do_mode_sense(fsg, bh); + break; + + case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: + fsg->data_size_from_cmnd = 0; + if ((reply = check_command(fsg, 6, DATA_DIR_NONE, + (1<<4), 0, + "PREVENT-ALLOW MEDIUM REMOVAL")) == 0) + reply = do_prevent_allow(fsg); + break; + + case SC_READ_6: + i = fsg->cmnd[4]; + fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, + (7<<1) | (1<<4), 1, + "READ(6)")) == 0) + reply = do_read(fsg); + break; + + case SC_READ_10: + fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]) << 9; + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "READ(10)")) == 0) + reply = do_read(fsg); + break; + + case SC_READ_12: + fsg->data_size_from_cmnd = get_be32(&fsg->cmnd[6]) << 9; + if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "READ(12)")) == 0) + reply = do_read(fsg); + break; + + case SC_READ_CAPACITY: + fsg->data_size_from_cmnd = 8; + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, + (0xf<<2) | (1<<8), 1, + "READ CAPACITY")) == 0) + reply = do_read_capacity(fsg, bh); + break; + + case SC_READ_FORMAT_CAPACITIES: + fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, + (3<<7), 1, + "READ FORMAT CAPACITIES")) == 0) + reply = do_read_format_capacities(fsg, bh); + break; + + case SC_REQUEST_SENSE: + fsg->data_size_from_cmnd = fsg->cmnd[4]; + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "REQUEST SENSE")) == 0) + reply = do_request_sense(fsg, bh); + break; + + case SC_START_STOP_UNIT: + fsg->data_size_from_cmnd = 0; + if ((reply = check_command(fsg, 6, DATA_DIR_NONE, + (1<<1) | (1<<4), 0, + "START-STOP UNIT")) == 0) + reply = do_start_stop(fsg); + break; + + case SC_SYNCHRONIZE_CACHE: + fsg->data_size_from_cmnd = 0; + if ((reply = check_command(fsg, 10, DATA_DIR_NONE, + (0xf<<2) | (3<<7), 1, + "SYNCHRONIZE CACHE")) == 0) + reply = do_synchronize_cache(fsg); + break; + + case SC_TEST_UNIT_READY: + fsg->data_size_from_cmnd = 0; + reply = check_command(fsg, 6, DATA_DIR_NONE, + 0, 1, + "TEST UNIT READY"); + break; + + /* Although optional, this command is used by MS-Windows. We + * support a minimal version: BytChk must be 0. */ + case SC_VERIFY: + fsg->data_size_from_cmnd = 0; + if ((reply = check_command(fsg, 10, DATA_DIR_NONE, + (1<<1) | (0xf<<2) | (3<<7), 1, + "VERIFY")) == 0) + reply = do_verify(fsg); + break; + + case SC_WRITE_6: + i = fsg->cmnd[4]; + fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; + if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, + (7<<1) | (1<<4), 1, + "WRITE(6)")) == 0) + reply = do_write(fsg); + break; + + case SC_WRITE_10: + fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]) << 9; + if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "WRITE(10)")) == 0) + reply = do_write(fsg); + break; + + case SC_WRITE_12: + fsg->data_size_from_cmnd = get_be32(&fsg->cmnd[6]) << 9; + if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "WRITE(12)")) == 0) + reply = do_write(fsg); + break; + + /* Some mandatory commands that we recognize but don't implement. + * They don't mean much in this setting. It's left as an exercise + * for anyone interested to implement RESERVE and RELEASE in terms + * of Posix locks. */ + case SC_FORMAT_UNIT: + case SC_RELEASE: + case SC_RESERVE: + case SC_SEND_DIAGNOSTIC: + // Fall through + + default: + fsg->data_size_from_cmnd = 0; + sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); + if ((reply = check_command(fsg, fsg->cmnd_size, + DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) { + fsg->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } + break; + } + up_read(&fsg->filesem); + + if (reply == -EINTR || signal_pending(current)) + return -EINTR; + + /* Set up the single reply buffer for finish_reply() */ + if (reply == -EINVAL) + reply = 0; // Error reply length + if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) { + reply = min((u32) reply, fsg->data_size_from_cmnd); + bh->inreq->length = reply; + bh->state = BUF_STATE_FULL; + fsg->residue -= reply; + } // Otherwise it's already set + + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct usb_request *req = bh->outreq; + struct bulk_cb_wrap *cbw = (struct bulk_cb_wrap *) req->buf; + + /* Was this a real packet? */ + if (req->status) + return -EINVAL; + + /* Is the CBW valid? */ + if (req->actual != USB_BULK_CB_WRAP_LEN || + cbw->Signature != __constant_cpu_to_le32( + USB_BULK_CB_SIG)) { + DBG(fsg, "invalid CBW: len %u sig 0x%x\n", + req->actual, + le32_to_cpu(cbw->Signature)); + + /* The Bulk-only spec says we MUST stall the bulk pipes! + * If we want to avoid stalls, set a flag so that we will + * clear the endpoint halts at the next reset. */ + if (!mod_data.can_stall) + set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags); + fsg_set_halt(fsg, fsg->bulk_out); + halt_bulk_in_endpoint(fsg); + return -EINVAL; + } + + /* Is the CBW meaningful? */ + if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + cbw->Length < 6 || cbw->Length > MAX_COMMAND_SIZE) { + DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " + "cmdlen %u\n", + cbw->Lun, cbw->Flags, cbw->Length); + + /* We can do anything we want here, so let's stall the + * bulk pipes if we are allowed to. */ + if (mod_data.can_stall) { + fsg_set_halt(fsg, fsg->bulk_out); + halt_bulk_in_endpoint(fsg); + } + return -EINVAL; + } + + /* Save the command for later */ + fsg->cmnd_size = cbw->Length; + memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); + if (cbw->Flags & USB_BULK_IN_FLAG) + fsg->data_dir = DATA_DIR_TO_HOST; + else + fsg->data_dir = DATA_DIR_FROM_HOST; + fsg->data_size = cbw->DataTransferLength; + if (fsg->data_size == 0) + fsg->data_dir = DATA_DIR_NONE; + fsg->lun = cbw->Lun; + fsg->tag = cbw->Tag; + return 0; +} + + +static int get_next_command(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh; + int rc = 0; + + if (transport_is_bbb()) { + + /* Wait for the next buffer to become available */ + bh = fsg->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + + /* Queue a request to read a Bulk-only CBW */ + set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); + start_transfer(fsg, fsg->bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state); + + /* We will drain the buffer in software, which means we + * can reuse it for the next filling. No need to advance + * next_buffhd_to_fill. */ + + /* Wait for the CBW to arrive */ + while (bh->state != BUF_STATE_FULL) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + rc = received_cbw(fsg, bh); + bh->state = BUF_STATE_EMPTY; + + } else { // USB_PR_CB or USB_PR_CBI + + /* Wait for the next command to arrive */ + while (fsg->cbbuf_cmnd_size == 0) { + if ((rc = sleep_thread(fsg)) != 0) + return rc; + } + + /* Is the previous status interrupt request still busy? + * The host is allowed to skip reading the status, + * so we must cancel it. */ + if (fsg->intreq_busy) + usb_ep_dequeue(fsg->intr_in, fsg->intreq); + + /* Copy the command and mark the buffer empty */ + fsg->data_dir = DATA_DIR_UNKNOWN; + spin_lock_irq(&fsg->lock); + fsg->cmnd_size = fsg->cbbuf_cmnd_size; + memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size); + fsg->cbbuf_cmnd_size = 0; + spin_unlock_irq(&fsg->lock); + } + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep, + const struct usb_endpoint_descriptor *d) +{ + int rc; + + ep->driver_data = fsg; + rc = usb_ep_enable(ep, d); + if (rc) + ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc); + return rc; +} + +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep, + struct usb_request **preq) +{ + *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (*preq) + return 0; + ERROR(fsg, "can't allocate request for %s\n", ep->name); + return -ENOMEM; +} + +/* + * Reset interface setting and re-init endpoint state (toggle etc). + * Call with altsetting < 0 to disable the interface. The only other + * available altsetting is 0, which enables the interface. + */ +static int do_set_interface(struct fsg_dev *fsg, int altsetting) +{ + int rc = 0; + int i; + const struct usb_endpoint_descriptor *d; + + if (fsg->running) + DBG(fsg, "reset interface\n"); + +reset: + /* Deallocate the requests */ + for (i = 0; i < NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &fsg->buffhds[i]; + + if (bh->inreq) { + usb_ep_free_request(fsg->bulk_in, bh->inreq); + bh->inreq = NULL; + } + if (bh->outreq) { + usb_ep_free_request(fsg->bulk_out, bh->outreq); + bh->outreq = NULL; + } + } + if (fsg->intreq) { + usb_ep_free_request(fsg->intr_in, fsg->intreq); + fsg->intreq = NULL; + } + + /* Disable the endpoints */ + if (fsg->bulk_in_enabled) { + usb_ep_disable(fsg->bulk_in); + fsg->bulk_in_enabled = 0; + } + if (fsg->bulk_out_enabled) { + usb_ep_disable(fsg->bulk_out); + fsg->bulk_out_enabled = 0; + } + if (fsg->intr_in_enabled) { + usb_ep_disable(fsg->intr_in); + fsg->intr_in_enabled = 0; + } + + fsg->running = 0; + if (altsetting < 0 || rc != 0) + return rc; + + DBG(fsg, "set interface %d\n", altsetting); + + /* Enable the endpoints */ + d = ep_desc(fsg->gadget, &fs_bulk_in_desc, &hs_bulk_in_desc); + if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) + goto reset; + fsg->bulk_in_enabled = 1; + + d = ep_desc(fsg->gadget, &fs_bulk_out_desc, &hs_bulk_out_desc); + if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) + goto reset; + fsg->bulk_out_enabled = 1; + + if (transport_is_cbi()) { + d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc); + if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) + goto reset; + fsg->intr_in_enabled = 1; + } + + /* Allocate the requests */ + for (i = 0; i < NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &fsg->buffhds[i]; + + if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) + goto reset; + if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) + goto reset; + bh->inreq->buf = bh->outreq->buf = bh->buf; + bh->inreq->dma = bh->outreq->dma = bh->dma; + bh->inreq->context = bh->outreq->context = bh; + bh->inreq->complete = bulk_in_complete; + bh->outreq->complete = bulk_out_complete; + } + if (transport_is_cbi()) { + if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0) + goto reset; + fsg->intreq->complete = intr_in_complete; + } + + fsg->running = 1; + for (i = 0; i < fsg->nluns; ++i) + fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; + return rc; +} + + +/* + * Change our operational configuration. This code must agree with the code + * that returns config descriptors, and with interface altsetting code. + * + * It's also responsible for power management interactions. Some + * configurations might not work with our current power sources. + * For now we just assume the gadget is always self-powered. + */ +static int do_set_config(struct fsg_dev *fsg, u8 new_config) +{ + int rc = 0; + + /* Disable the single interface */ + if (fsg->config != 0) { + DBG(fsg, "reset config\n"); + fsg->config = 0; + rc = do_set_interface(fsg, -1); + } + + /* Enable the interface */ + if (new_config != 0) { + fsg->config = new_config; + if ((rc = do_set_interface(fsg, 0)) != 0) + fsg->config = 0; // Reset on errors + else { + char *speed; + + switch (fsg->gadget->speed) { + case USB_SPEED_LOW: speed = "low"; break; + case USB_SPEED_FULL: speed = "full"; break; + case USB_SPEED_HIGH: speed = "high"; break; + default: speed = "?"; break; + } + INFO(fsg, "%s speed config #%d\n", speed, fsg->config); + } + } + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static void handle_exception(struct fsg_dev *fsg) +{ + siginfo_t info; + int sig; + int i; + int num_active; + struct fsg_buffhd *bh; + enum fsg_state old_state; + u8 new_config; + struct lun *curlun; + unsigned int exception_req_tag; + int rc; + + /* Clear the existing signals. Anything but SIGUSR1 is converted + * into a high-priority EXIT exception. */ + for (;;) { + sig = dequeue_signal_lock(current, &fsg->thread_signal_mask, + &info); + if (!sig) + break; + if (sig != SIGUSR1) { + if (fsg->state < FSG_STATE_EXIT) + DBG(fsg, "Main thread exiting on signal\n"); + raise_exception(fsg, FSG_STATE_EXIT); + } + } + + /* Cancel all the pending transfers */ + if (fsg->intreq_busy) + usb_ep_dequeue(fsg->intr_in, fsg->intreq); + for (i = 0; i < NUM_BUFFERS; ++i) { + bh = &fsg->buffhds[i]; + if (bh->inreq_busy) + usb_ep_dequeue(fsg->bulk_in, bh->inreq); + if (bh->outreq_busy) + usb_ep_dequeue(fsg->bulk_out, bh->outreq); + } + + /* Wait until everything is idle */ + for (;;) { + num_active = fsg->intreq_busy; + for (i = 0; i < NUM_BUFFERS; ++i) { + bh = &fsg->buffhds[i]; + num_active += bh->inreq_busy + bh->outreq_busy; + } + if (num_active == 0) + break; + if (sleep_thread(fsg)) + return; + } + + /* Clear out the controller's fifos */ + if (fsg->bulk_in_enabled) + usb_ep_fifo_flush(fsg->bulk_in); + if (fsg->bulk_out_enabled) + usb_ep_fifo_flush(fsg->bulk_out); + if (fsg->intr_in_enabled) + usb_ep_fifo_flush(fsg->intr_in); + + /* Reset the I/O buffer states and pointers, the SCSI + * state, and the exception. Then invoke the handler. */ + spin_lock_irq(&fsg->lock); + + for (i = 0; i < NUM_BUFFERS; ++i) { + bh = &fsg->buffhds[i]; + bh->state = BUF_STATE_EMPTY; + } + fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = + &fsg->buffhds[0]; + + exception_req_tag = fsg->exception_req_tag; + new_config = fsg->new_config; + old_state = fsg->state; + + if (old_state == FSG_STATE_ABORT_BULK_OUT) + fsg->state = FSG_STATE_STATUS_PHASE; + else { + for (i = 0; i < fsg->nluns; ++i) { + curlun = &fsg->luns[i]; + curlun->prevent_medium_removal = 0; + curlun->sense_data = curlun->unit_attention_data = + SS_NO_SENSE; + curlun->sense_data_info = 0; + } + fsg->state = FSG_STATE_IDLE; + } + spin_unlock_irq(&fsg->lock); + + /* Carry out any extra actions required for the exception */ + switch (old_state) { + default: + break; + + case FSG_STATE_ABORT_BULK_OUT: + send_status(fsg); + spin_lock_irq(&fsg->lock); + if (fsg->state == FSG_STATE_STATUS_PHASE) + fsg->state = FSG_STATE_IDLE; + spin_unlock_irq(&fsg->lock); + break; + + case FSG_STATE_RESET: + /* In case we were forced against our will to halt a + * bulk endpoint, clear the halt now. (The SuperH UDC + * requires this.) */ + if (test_and_clear_bit(CLEAR_BULK_HALTS, + &fsg->atomic_bitflags)) { + usb_ep_clear_halt(fsg->bulk_in); + usb_ep_clear_halt(fsg->bulk_out); + } + + if (transport_is_bbb()) { + if (fsg->ep0_req_tag == exception_req_tag) + ep0_queue(fsg); // Complete the status stage + + } else if (transport_is_cbi()) + send_status(fsg); // Status by interrupt pipe + + /* Technically this should go here, but it would only be + * a waste of time. Ditto for the INTERFACE_CHANGE and + * CONFIG_CHANGE cases. */ + // for (i = 0; i < fsg->nluns; ++i) + // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; + break; + + case FSG_STATE_INTERFACE_CHANGE: + rc = do_set_interface(fsg, 0); + if (fsg->ep0_req_tag != exception_req_tag) + break; + if (rc != 0) // STALL on errors + fsg_set_halt(fsg, fsg->ep0); + else // Complete the status stage + ep0_queue(fsg); + break; + + case FSG_STATE_CONFIG_CHANGE: + rc = do_set_config(fsg, new_config); + if (fsg->ep0_req_tag != exception_req_tag) + break; + if (rc != 0) // STALL on errors + fsg_set_halt(fsg, fsg->ep0); + else // Complete the status stage + ep0_queue(fsg); + break; + + case FSG_STATE_DISCONNECT: + fsync_all(fsg); + do_set_config(fsg, 0); // Unconfigured state + break; + + case FSG_STATE_EXIT: + case FSG_STATE_TERMINATED: + do_set_config(fsg, 0); // Free resources + spin_lock_irq(&fsg->lock); + fsg->state = FSG_STATE_TERMINATED; // Stop the thread + spin_unlock_irq(&fsg->lock); + break; + } +} + + +/*-------------------------------------------------------------------------*/ + +static int fsg_main_thread(void *fsg_) +{ + struct fsg_dev *fsg = (struct fsg_dev *) fsg_; + + fsg->thread_task = current; + + /* Release all our userspace resources */ + daemonize("file-storage-gadget"); + + /* Allow the thread to be killed by a signal, but set the signal mask + * to block everything but INT, TERM, KILL, and USR1. */ + siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) | + sigmask(SIGTERM) | sigmask(SIGKILL) | + sigmask(SIGUSR1)); + sigprocmask(SIG_SETMASK, &fsg->thread_signal_mask, NULL); + + /* Arrange for userspace references to be interpreted as kernel + * pointers. That way we can pass a kernel pointer to a routine + * that expects a __user pointer and it will work okay. */ + set_fs(get_ds()); + + /* Wait for the gadget registration to finish up */ + wait_for_completion(&fsg->thread_notifier); + + /* The main loop */ + while (fsg->state != FSG_STATE_TERMINATED) { + if (exception_in_progress(fsg) || signal_pending(current)) { + handle_exception(fsg); + continue; + } + + if (!fsg->running) { + sleep_thread(fsg); + continue; + } + + if (get_next_command(fsg)) + continue; + + spin_lock_irq(&fsg->lock); + if (!exception_in_progress(fsg)) + fsg->state = FSG_STATE_DATA_PHASE; + spin_unlock_irq(&fsg->lock); + + if (do_scsi_command(fsg) || finish_reply(fsg)) + continue; + + spin_lock_irq(&fsg->lock); + if (!exception_in_progress(fsg)) + fsg->state = FSG_STATE_STATUS_PHASE; + spin_unlock_irq(&fsg->lock); + + if (send_status(fsg)) + continue; + + spin_lock_irq(&fsg->lock); + if (!exception_in_progress(fsg)) + fsg->state = FSG_STATE_IDLE; + spin_unlock_irq(&fsg->lock); + } + + fsg->thread_task = NULL; + flush_signals(current); + + /* In case we are exiting because of a signal, unregister the + * gadget driver and close the backing file. */ + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) { + usb_gadget_unregister_driver(&fsg_driver); + close_all_backing_files(fsg); + } + + /* Let the unbind and cleanup routines know the thread has exited */ + complete_and_exit(&fsg->thread_notifier, 0); +} + + +/*-------------------------------------------------------------------------*/ + +/* If the next two routines are called while the gadget is registered, + * the caller must own fsg->filesem for writing. */ + +static int NORMALLY_INIT open_backing_file(struct lun *curlun, + const char *filename) +{ + int ro; + struct file *filp = NULL; + int rc = -EINVAL; + struct inode *inode = NULL; + loff_t size; + loff_t num_sectors; + + /* R/W if we can, R/O if we must */ + ro = curlun->ro; + if (!ro) { + filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); + if (-EROFS == PTR_ERR(filp)) + ro = 1; + } + if (ro) + filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); + if (IS_ERR(filp)) { + LINFO(curlun, "unable to open backing file: %s\n", filename); + return PTR_ERR(filp); + } + + if (!(filp->f_mode & FMODE_WRITE)) + ro = 1; + + if (filp->f_dentry) + inode = filp->f_dentry->d_inode; + if (inode && S_ISBLK(inode->i_mode)) { + if (bdev_read_only(inode->i_bdev)) + ro = 1; + } else if (!inode || !S_ISREG(inode->i_mode)) { + LINFO(curlun, "invalid file type: %s\n", filename); + goto out; + } + + /* If we can't read the file, it's no good. + * If we can't write the file, use it read-only. */ + if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { + LINFO(curlun, "file not readable: %s\n", filename); + goto out; + } + if (!(filp->f_op->write || filp->f_op->aio_write)) + ro = 1; + + size = i_size_read(inode->i_mapping->host); + if (size < 0) { + LINFO(curlun, "unable to find file size: %s\n", filename); + rc = (int) size; + goto out; + } + num_sectors = size >> 9; // File size in 512-byte sectors + if (num_sectors == 0) { + LINFO(curlun, "file too small: %s\n", filename); + rc = -ETOOSMALL; + goto out; + } + + get_file(filp); + curlun->ro = ro; + curlun->filp = filp; + curlun->file_length = size; + curlun->num_sectors = num_sectors; + LDBG(curlun, "open backing file: %s\n", filename); + rc = 0; + +out: + filp_close(filp, current->files); + return rc; +} + + +static void close_backing_file(struct lun *curlun) +{ + if (curlun->filp) { + LDBG(curlun, "close backing file\n"); + fput(curlun->filp); + curlun->filp = NULL; + } +} + +static void close_all_backing_files(struct fsg_dev *fsg) +{ + int i; + + for (i = 0; i < fsg->nluns; ++i) + close_backing_file(&fsg->luns[i]); +} + + +static ssize_t show_ro(struct device *dev, char *buf) +{ + struct lun *curlun = dev_to_lun(dev); + + return sprintf(buf, "%d\n", curlun->ro); +} + +static ssize_t show_file(struct device *dev, char *buf) +{ + struct lun *curlun = dev_to_lun(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + char *p; + ssize_t rc; + + down_read(&fsg->filesem); + if (backing_file_is_open(curlun)) { // Get the complete pathname + p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt, + buf, PAGE_SIZE - 1); + if (IS_ERR(p)) + rc = PTR_ERR(p); + else { + rc = strlen(p); + memmove(buf, p, rc); + buf[rc] = '\n'; // Add a newline + buf[++rc] = 0; + } + } else { // No file, return 0 bytes + *buf = 0; + rc = 0; + } + up_read(&fsg->filesem); + return rc; +} + + +ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf, + size_t count) +{ + ssize_t rc = count; + struct lun *curlun = dev_to_lun(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + int i; + + if (sscanf(buf, "%d", &i) != 1) + return -EINVAL; + + /* Allow the write-enable status to change only while the backing file + * is closed. */ + down_read(&fsg->filesem); + if (backing_file_is_open(curlun)) { + LDBG(curlun, "read-only status change prevented\n"); + rc = -EBUSY; + } else { + curlun->ro = !!i; + LDBG(curlun, "read-only status set to %d\n", curlun->ro); + } + up_read(&fsg->filesem); + return rc; +} + +ssize_t NORMALLY_INIT store_file(struct device *dev, const char *buf, + size_t count) +{ + struct lun *curlun = dev_to_lun(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + int rc = 0; + + if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) { + LDBG(curlun, "eject attempt prevented\n"); + return -EBUSY; // "Door is locked" + } + + /* Remove a trailing newline */ + if (count > 0 && buf[count-1] == '\n') + ((char *) buf)[count-1] = 0; // Ugh! + + /* Eject current medium */ + down_write(&fsg->filesem); + if (backing_file_is_open(curlun)) { + close_backing_file(curlun); + curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; + } + + /* Load new medium */ + if (count > 0 && buf[0]) { + rc = open_backing_file(curlun, buf); + if (rc == 0) + curlun->unit_attention_data = + SS_NOT_READY_TO_READY_TRANSITION; + } + up_write(&fsg->filesem); + return (rc < 0 ? rc : count); +} + + +/* The write permissions and store_xxx pointers are set in fsg_bind() */ +static DEVICE_ATTR(ro, 0444, show_ro, NULL); +static DEVICE_ATTR(file, 0444, show_file, NULL); + + +/*-------------------------------------------------------------------------*/ + +static void fsg_unbind(struct usb_gadget *gadget) +{ + struct fsg_dev *fsg = get_gadget_data(gadget); + int i; + struct lun *curlun; + struct usb_request *req = fsg->ep0req; + + DBG(fsg, "unbind\n"); + clear_bit(REGISTERED, &fsg->atomic_bitflags); + + /* Unregister the sysfs attribute files and the LUNs */ + for (i = 0; i < fsg->nluns; ++i) { + curlun = &fsg->luns[i]; + if (curlun->registered) { + device_remove_file(&curlun->dev, &dev_attr_ro); + device_remove_file(&curlun->dev, &dev_attr_file); + device_unregister_wait(&curlun->dev); + curlun->registered = 0; + } + } + + /* If the thread isn't already dead, tell it to exit now */ + if (fsg->state != FSG_STATE_TERMINATED) { + raise_exception(fsg, FSG_STATE_EXIT); + wait_for_completion(&fsg->thread_notifier); + + /* The cleanup routine waits for this completion also */ + complete(&fsg->thread_notifier); + } + + /* Free the data buffers */ + for (i = 0; i < NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &fsg->buffhds[i]; + + if (bh->buf) + usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma, + mod_data.buflen); + } + + /* Free the request and buffer for endpoint 0 */ + if (req) { + if (req->buf) + usb_ep_free_buffer(fsg->ep0, req->buf, + req->dma, EP0_BUFSIZE); + usb_ep_free_request(fsg->ep0, req); + } + + set_gadget_data(gadget, 0); +} + + +static int __init check_parameters(struct fsg_dev *fsg) +{ + int prot; + + /* Store the default values */ + mod_data.transport_type = USB_PR_BULK; + mod_data.transport_name = "Bulk-only"; + mod_data.protocol_type = USB_SC_SCSI; + mod_data.protocol_name = "Transparent SCSI"; + + prot = simple_strtol(mod_data.protocol_parm, NULL, 0); + +#ifdef CONFIG_USB_FILE_STORAGE_TEST + if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) { + ; // Use default setting + } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) { + mod_data.transport_type = USB_PR_CB; + mod_data.transport_name = "Control-Bulk"; + } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) { + mod_data.transport_type = USB_PR_CBI; + mod_data.transport_name = "Control-Bulk-Interrupt"; + } else { + INFO(fsg, "invalid transport: %s\n", mod_data.transport_parm); + return -EINVAL; + } + + if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 || + prot == USB_SC_SCSI) { + ; // Use default setting + } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 || + prot == USB_SC_RBC) { + mod_data.protocol_type = USB_SC_RBC; + mod_data.protocol_name = "RBC"; + } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 || + strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 || + prot == USB_SC_8020) { + mod_data.protocol_type = USB_SC_8020; + mod_data.protocol_name = "8020i (ATAPI)"; + } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 || + prot == USB_SC_QIC) { + mod_data.protocol_type = USB_SC_QIC; + mod_data.protocol_name = "QIC-157"; + } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 || + prot == USB_SC_UFI) { + mod_data.protocol_type = USB_SC_UFI; + mod_data.protocol_name = "UFI"; + } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 || + prot == USB_SC_8070) { + mod_data.protocol_type = USB_SC_8070; + mod_data.protocol_name = "8070i"; + } else { + INFO(fsg, "invalid protocol: %s\n", mod_data.protocol_parm); + return -EINVAL; + } + + mod_data.buflen &= PAGE_CACHE_MASK; + if (mod_data.buflen <= 0) { + INFO(fsg, "invalid buflen\n"); + return -ETOOSMALL; + } +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ + + return 0; +} + + +static int __init fsg_bind(struct usb_gadget *gadget) +{ + struct fsg_dev *fsg = the_fsg; + int rc; + int i; + struct lun *curlun; + struct usb_ep *ep; + struct usb_request *req; + char *pathbuf, *p; + + fsg->gadget = gadget; + set_gadget_data(gadget, fsg); + fsg->ep0 = gadget->ep0; + fsg->ep0->driver_data = fsg; + + if ((rc = check_parameters(fsg)) != 0) + goto out; + + if (mod_data.removable) { // Enable the store_xxx attributes + dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644; + dev_attr_ro.store = store_ro; + dev_attr_file.store = store_file; + } + + /* Find out how many LUNs there should be */ + i = mod_data.nluns; + if (i == 0) + i = max(mod_data.num_filenames, 1); + if (i > MAX_LUNS) { + INFO(fsg, "invalid number of LUNs: %d\n", i); + rc = -EINVAL; + goto out; + } + + /* Create the LUNs and open their backing files. We can't register + * the LUN devices until the gadget itself is registered, which + * doesn't happen until after fsg_bind() returns. */ + fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL); + if (!fsg->luns) { + rc = -ENOMEM; + goto out; + } + memset(fsg->luns, 0, i * sizeof(struct lun)); + fsg->nluns = i; + + for (i = 0; i < fsg->nluns; ++i) { + curlun = &fsg->luns[i]; + curlun->ro = ro[i]; + curlun->dev.parent = &gadget->dev; + curlun->dev.driver = &fsg_driver.driver; + dev_set_drvdata(&curlun->dev, fsg); + snprintf(curlun->dev.bus_id, BUS_ID_SIZE, + "%s-lun%d", gadget->dev.bus_id, i); + + if (file[i] && *file[i]) { + if ((rc = open_backing_file(curlun, file[i])) != 0) + goto out; + } else if (!mod_data.removable) { + INFO(fsg, "no file given for LUN%d\n", i); + rc = -EINVAL; + goto out; + } + } + + /* Fix up the descriptors */ + device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket; +#ifdef HIGHSPEED + dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; // ??? +#endif + device_desc.idVendor = cpu_to_le16(mod_data.vendor); + device_desc.idProduct = cpu_to_le16(mod_data.product); + device_desc.bcdDevice = cpu_to_le16(mod_data.release); + + i = (transport_is_cbi() ? 3 : 2); // Number of endpoints + config_desc.wTotalLength = USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE + + USB_DT_ENDPOINT_SIZE * i; + intf_desc.bNumEndpoints = i; + intf_desc.bInterfaceSubClass = mod_data.protocol_type; + intf_desc.bInterfaceProtocol = mod_data.transport_type; + + /* Find all the endpoints we will use */ + gadget_for_each_ep(ep, gadget) { + if (strcmp(ep->name, EP_BULK_IN_NAME) == 0) + fsg->bulk_in = ep; + else if (strcmp(ep->name, EP_BULK_OUT_NAME) == 0) + fsg->bulk_out = ep; + else if (strcmp(ep->name, EP_INTR_IN_NAME) == 0) + fsg->intr_in = ep; + } + if (!fsg->bulk_in || !fsg->bulk_out || + (transport_is_cbi() && !fsg->intr_in)) { + DBG(fsg, "unable to find all endpoints\n"); + rc = -ENOTSUPP; + goto out; + } + fsg->bulk_out_maxpacket = (gadget->speed == USB_SPEED_HIGH ? 512 : + FS_BULK_OUT_MAXPACKET); + + rc = -ENOMEM; + + /* Allocate the request and buffer for endpoint 0 */ + fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); + if (!req) + goto out; + req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE, + &req->dma, GFP_KERNEL); + if (!req->buf) + goto out; + req->complete = ep0_complete; + + /* Allocate the data buffers */ + for (i = 0; i < NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &fsg->buffhds[i]; + + bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen, + &bh->dma, GFP_KERNEL); + if (!bh->buf) + goto out; + bh->next = bh + 1; + } + fsg->buffhds[NUM_BUFFERS - 1].next = &fsg->buffhds[0]; + + /* This should reflect the actual gadget power source */ + usb_gadget_set_selfpowered(gadget); + + /* On a real device, serial[] would be loaded from permanent + * storage. We just encode it from the driver version string. */ + for (i = 0; i < sizeof(serial) - 2; i += 2) { + unsigned char c = DRIVER_VERSION[i / 2]; + + if (!c) + break; + sprintf(&serial[i], "%02X", c); + } + + if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS | + CLONE_FILES))) < 0) + goto out; + fsg->thread_pid = rc; + + INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); + INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); + + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); + for (i = 0; i < fsg->nluns; ++i) { + curlun = &fsg->luns[i]; + if (backing_file_is_open(curlun)) { + p = NULL; + if (pathbuf) { + p = d_path(curlun->filp->f_dentry, + curlun->filp->f_vfsmnt, + pathbuf, PATH_MAX); + if (IS_ERR(p)) + p = NULL; + } + LINFO(curlun, "ro=%d, file: %s\n", + curlun->ro, (p ? p : "(error)")); + } + } + kfree(pathbuf); + + DBG(fsg, "transport=%s (x%02x)\n", + mod_data.transport_name, mod_data.transport_type); + DBG(fsg, "protocol=%s (x%02x)\n", + mod_data.protocol_name, mod_data.protocol_type); + DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", + mod_data.vendor, mod_data.product, mod_data.release); + DBG(fsg, "removable=%d, stall=%d, buflen=%u\n", + mod_data.removable, mod_data.can_stall, + mod_data.buflen); + DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid); + return 0; + +out: + fsg->state = FSG_STATE_TERMINATED; // The thread is dead + fsg_unbind(gadget); + close_all_backing_files(fsg); + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static struct usb_gadget_driver fsg_driver = { +#ifdef HIGHSPEED + .speed = USB_SPEED_HIGH, +#else + .speed = USB_SPEED_FULL, +#endif + .function = (char *) longname, + .bind = fsg_bind, + .unbind = fsg_unbind, + .disconnect = fsg_disconnect, + .setup = fsg_setup, + + .driver = { + .name = (char *) shortname, + // .release = ... + // .suspend = ... + // .resume = ... + }, +}; + + +static int __init fsg_alloc(void) +{ + struct fsg_dev *fsg; + + fsg = kmalloc(sizeof *fsg, GFP_KERNEL); + if (!fsg) + return -ENOMEM; + memset(fsg, 0, sizeof *fsg); + spin_lock_init(&fsg->lock); + init_rwsem(&fsg->filesem); + init_waitqueue_head(&fsg->thread_wqh); + init_completion(&fsg->thread_notifier); + + the_fsg = fsg; + return 0; +} + + +static void fsg_free(struct fsg_dev *fsg) +{ + kfree(fsg->luns); + kfree(fsg); +} + + +static int __init fsg_init(void) +{ + int rc; + struct fsg_dev *fsg; + int i; + struct lun *curlun; + + if ((rc = fsg_alloc()) != 0) + return rc; + fsg = the_fsg; + if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) { + fsg_free(fsg); + return rc; + } + set_bit(REGISTERED, &fsg->atomic_bitflags); + + /* Register the LUN devices and their attribute files */ + for (i = 0; i < fsg->nluns; ++i) { + curlun = &fsg->luns[i]; + if ((rc = device_register(&curlun->dev)) != 0) + INFO(fsg, "failed to register LUN%d: %d\n", i, rc); + else { + curlun->registered = 1; + device_create_file(&curlun->dev, &dev_attr_ro); + device_create_file(&curlun->dev, &dev_attr_file); + } + } + + /* Tell the thread to start working */ + complete(&fsg->thread_notifier); + return 0; +} +module_init(fsg_init); + + +static void __exit fsg_cleanup(void) +{ + struct fsg_dev *fsg = the_fsg; + + /* Unregister the driver iff the thread hasn't already done so */ + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) + usb_gadget_unregister_driver(&fsg_driver); + + /* Wait for the thread to finish up */ + wait_for_completion(&fsg->thread_notifier); + + close_all_backing_files(fsg); + fsg_free(fsg); +} +module_exit(fsg_cleanup); diff -urN linux-2.6.2-rc2/drivers/usb/gadget/inode.c linux-2.6.2-rc3/drivers/usb/gadget/inode.c --- linux-2.6.2-rc2/drivers/usb/gadget/inode.c 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/inode.c 2004-01-30 18:49:23.000000000 -0800 @@ -232,18 +232,27 @@ * the usb controller exposes. */ -#ifdef CONFIG_USB_GADGETFS_NET2280 +#ifdef CONFIG_USB_GADGET_DUMMY_HCD +/* act (mostly) like a net2280 */ +#define CONFIG_USB_GADGET_NET2280 +#endif + +#ifdef CONFIG_USB_GADGET_NET2280 #define CHIP "net2280" #define HIGHSPEED #endif -#ifdef CONFIG_USB_GADGETFS_PXA2XX +#ifdef CONFIG_USB_GADGET_PXA2XX #define CHIP "pxa2xx_udc" /* earlier hardware doesn't have UDCCFR, races set_{config,interface} */ #warning works best with pxa255 or newer #endif -#ifdef CONFIG_USB_GADGETFS_SA1100 +#ifdef CONFIG_USB_GADGET_GOKU +#define CHIP "goku_udc" +#endif + +#ifdef CONFIG_USB_GADGET_SA1100 #define CHIP "sa1100" #endif @@ -397,7 +406,7 @@ /* handle a synchronous OUT bulk/intr/iso transfer */ static ssize_t -ep_read (struct file *fd, char *buf, size_t len, loff_t *ptr) +ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) { struct ep_data *data = fd->private_data; void *kbuf; @@ -441,7 +450,7 @@ /* handle a synchronous IN bulk/intr/iso transfer */ static ssize_t -ep_write (struct file *fd, const char *buf, size_t len, loff_t *ptr) +ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) { struct ep_data *data = fd->private_data; void *kbuf; diff -urN linux-2.6.2-rc2/drivers/usb/gadget/net2280.c linux-2.6.2-rc3/drivers/usb/gadget/net2280.c --- linux-2.6.2-rc2/drivers/usb/gadget/net2280.c 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/net2280.c 2004-01-30 18:49:23.000000000 -0800 @@ -25,9 +25,6 @@ * rev1 chips. Rev1a silicon (0110) fixes almost all of them. */ -#define USE_DMA_CHAINING - - /* * Copyright (C) 2003 David Brownell * Copyright (C) 2003 NetChip Technologies @@ -47,8 +44,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define DEBUG 1 -// #define VERBOSE /* extra debug messages (success too) */ +#undef DEBUG /* messages on error and most fault paths */ +#undef VERBOSE /* extra debug messages (success too) */ #include #include @@ -77,7 +74,7 @@ #define DRIVER_DESC "NetChip 2280 USB Peripheral Controller" -#define DRIVER_VERSION "Bastille Day 2003" +#define DRIVER_VERSION "2004 Jan 14" #define DMA_ADDR_INVALID (~(dma_addr_t)0) #define EP_DONTUSE 13 /* nonzero */ @@ -96,10 +93,21 @@ "ep-e", "ep-f", }; +/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO) + * use_dma_chaining -- dma descriptor queueing gives even more irq reduction + * + * The net2280 DMA engines are not tightly integrated with their FIFOs; + * not all cases are (yet) handled well in this driver or the silicon. + * Some gadget drivers work better with the dma support here than others. + * These two parameters let you use PIO or more aggressive DMA. + */ static int use_dma = 1; +static int use_dma_chaining = 0; /* "modprobe net2280 use_dma=n" etc */ -module_param (use_dma, bool, S_IRUGO|S_IWUSR); +module_param (use_dma, bool, S_IRUGO); +module_param (use_dma_chaining, bool, S_IRUGO); + /* mode 0 == ep-{a,b,c,d} 1K fifo each * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable @@ -110,6 +118,7 @@ /* "modprobe net2280 fifo_mode=1" etc */ module_param (fifo_mode, ushort, 0644); + #define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") #if defined(USE_SYSFS_DEBUG_FILES) || defined (DEBUG) @@ -162,6 +171,7 @@ /* ep_reset() has already been called */ ep->stopped = 0; + ep->out_overflow = 0; /* set speed-dependent max packet; may kick in high bandwidth */ set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max); @@ -169,8 +179,8 @@ /* FIFO lines can't go to different packets. PIO is ok, so * use it instead of troublesome (non-bulk) multi-packet DMA. */ - if (ep->is_in && ep->dma && (max % 4) != 0) { - DEBUG (ep->dev, "%s, no IN dma for maxpacket %d\n", + if (ep->dma && (max % 4) != 0 && use_dma_chaining) { + DEBUG (ep->dev, "%s, no dma for maxpacket %d\n", ep->ep.name, ep->ep.maxpacket); ep->dma = 0; } @@ -179,17 +189,21 @@ writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat); tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); if (tmp == USB_ENDPOINT_XFER_INT) { - /* not just because of erratum 0105; avoid ever - * kicking in the "toggle-irrelevant" mode. - */ - tmp = USB_ENDPOINT_XFER_BULK; + /* erratum 0105 workaround prevents hs NYET */ + if (dev->chiprev == 0100 + && dev->gadget.speed == USB_SPEED_HIGH + && !(desc->bEndpointAddress & USB_DIR_IN)) + writel ((1 << CLEAR_NAK_OUT_PACKETS_MODE), + &ep->regs->ep_rsp); } else if (tmp == USB_ENDPOINT_XFER_BULK) { /* catch some particularly blatant driver bugs */ if ((dev->gadget.speed == USB_SPEED_HIGH && max != 512) || (dev->gadget.speed == USB_SPEED_FULL - && max > 64)) + && max > 64)) { + spin_unlock_irqrestore (&dev->lock, flags); return -ERANGE; + } } ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0; tmp <<= ENDPOINT_TYPE; @@ -205,11 +219,6 @@ writel (tmp, &ep->regs->ep_cfg); -#ifdef NET2280_DMA_OUT_WORKAROUND - if (!ep->is_in) - ep->dma = 0; -#endif - /* enable irqs */ if (!ep->dma) { /* pio, per-packet */ tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0); @@ -388,6 +397,7 @@ } td->dmacount = 0; /* not VALID */ td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmadesc = td->dmaaddr; req->td = td; } return &req->req; @@ -541,8 +551,11 @@ count -= 4; } - /* last fifo entry is "short" unless we wrote a full packet */ - if (total < ep->ep.maxpacket) { + /* last fifo entry is "short" unless we wrote a full packet. + * also explicitly validate last word in (periodic) transfers + * when maxpacket is not a multiple of 4 bytes. + */ + if (count || total < ep->ep.maxpacket) { tmp = count ? get_unaligned ((u32 *)buf) : count; cpu_to_le32s (&tmp); set_fifo_bytecount (ep, count & 0x03); @@ -555,6 +568,9 @@ /* work around erratum 0106: PCI and USB race over the OUT fifo. * caller guarantees chiprev 0100, out endpoint is NAKing, and * there's no real data in the fifo. + * + * NOTE: also used in cases where that erratum doesn't apply: + * where the host wrote "too much" data to us. */ static void out_flush (struct net2280_ep *ep) { @@ -599,13 +615,13 @@ /* erratum 0106 ... packets coming in during fifo reads might * be incompletely rejected. not all cases have workarounds. */ - if (ep->dev->chiprev == 0x0100) { + if (ep->dev->chiprev == 0x0100 + && ep->dev->gadget.speed == USB_SPEED_FULL) { + udelay (1); tmp = readl (&ep->regs->ep_stat); if ((tmp & (1 << NAK_OUT_PACKETS))) - /* cleanup = 1 */; - else if ((tmp & (1 << FIFO_FULL)) - /* don't break hs PING protocol ... */ - || ep->dev->gadget.speed == USB_SPEED_FULL) { + cleanup = 1; + else if ((tmp & (1 << FIFO_FULL))) { start_out_naking (ep); prevent = 1; } @@ -617,6 +633,15 @@ */ prefetchw (buf); count = readl (®s->ep_avail); + if (unlikely (count == 0)) { + udelay (1); + tmp = readl (&ep->regs->ep_stat); + count = readl (®s->ep_avail); + /* handled that data already? */ + if (count == 0 && (tmp & (1 << NAK_OUT_PACKETS)) == 0) + return 0; + } + tmp = req->req.length - req->req.actual; if (count > tmp) { /* as with DMA, data overflow gets flushed */ @@ -626,7 +651,10 @@ ep->ep.name, count, tmp); req->req.status = -EOVERFLOW; cleanup = 1; - } + /* NAK_OUT_PACKETS will be set, so flushing is safe; + * the next read will start with the next packet + */ + } /* else it's a ZLP, no worries */ count = tmp; } req->req.actual += count; @@ -665,7 +693,7 @@ } /* fill out dma descriptor to match a given request */ -static inline void +static void fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) { struct net2280_dma *td = req->td; @@ -678,15 +706,13 @@ */ if (ep->is_in) dmacount |= (1 << DMA_DIRECTION); - else + else if ((dmacount % ep->ep.maxpacket) != 0) dmacount |= (1 << END_OF_CHAIN); req->valid = valid; if (valid) dmacount |= (1 << VALID_BIT); -#ifdef USE_DMA_CHAINING - if (!req->req.no_interrupt) -#endif + if (likely(!req->req.no_interrupt || !use_dma_chaining)) dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE); /* td->dmadesc = previously set by caller */ @@ -698,7 +724,8 @@ } static const u32 dmactl_default = - (1 << DMA_CLEAR_COUNT_ENABLE) + (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT) + | (1 << DMA_CLEAR_COUNT_ENABLE) /* erratum 0116 workaround part 1 (use POLLING) */ | (POLL_100_USEC << DESCRIPTOR_POLLING_RATE) | (1 << DMA_VALID_BIT_POLLING_ENABLE) @@ -714,18 +741,41 @@ static inline void stop_dma (struct net2280_dma_regs *dma) { - writel (dmactl_default & ~(1 << DMA_ENABLE), &dma->dmactl); + writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl); spin_stop_dma (dma); } +static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma) +{ + struct net2280_dma_regs *dma = ep->dma; + + writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION), + &dma->dmacount); + writel (readl (&dma->dmastat), &dma->dmastat); + + writel (td_dma, &dma->dmadesc); + writel (dmactl, &dma->dmactl); + + /* erratum 0116 workaround part 3: pci arbiter away from net2280 */ + (void) readl (&ep->dev->pci->pcimstctl); + + writel ((1 << DMA_START), &dma->dmastat); + + if (!ep->is_in) + stop_out_naking (ep); +} + static void start_dma (struct net2280_ep *ep, struct net2280_request *req) { u32 tmp; - int clear_nak = 0; struct net2280_dma_regs *dma = ep->dma; /* FIXME can't use DMA for ZLPs */ + /* on this path we "know" there's no dma active (yet) */ + WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE)); + writel (0, &ep->dma->dmactl); + /* previous OUT packet might have been short */ if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat)) & (1 << NAK_OUT_PACKETS)) != 0) { @@ -733,9 +783,9 @@ &ep->regs->ep_stat); tmp = readl (&ep->regs->ep_avail); - if (tmp == 0) - clear_nak = 1; - else { + if (tmp) { + writel (readl (&dma->dmastat), &dma->dmastat); + /* transfer all/some fifo data */ writel (req->req.dma, &dma->dmaaddr); tmp = min (tmp, req->req.length); @@ -744,6 +794,8 @@ req->td->dmacount = cpu_to_le32 (req->req.length - tmp); writel ((1 << DMA_DONE_INTERRUPT_ENABLE) | tmp, &dma->dmacount); + req->td->dmadesc = 0; + req->valid = 1; writel ((1 << DMA_ENABLE), &dma->dmactl); writel ((1 << DMA_START), &dma->dmastat); @@ -751,8 +803,6 @@ } } - /* on this path we know there's no dma queue (yet) */ - WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE)); tmp = dmactl_default; /* force packet boundaries between dma requests, but prevent the @@ -772,25 +822,10 @@ req->td->dmadesc = cpu_to_le32 (ep->td_dma); fill_dma_desc (ep, req, 1); -#ifdef USE_DMA_CHAINING - writel ( (1 << VALID_BIT) - | (ep->is_in << DMA_DIRECTION) - | 0, &dma->dmacount); -#else - req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); -#endif - - writel (req->td_dma, &dma->dmadesc); - writel (tmp, &dma->dmactl); + if (!use_dma_chaining) + req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); - /* erratum 0116 workaround part 3: pci arbiter away from net2280 */ - (void) readl (&ep->dev->pci->pcimstctl); - - writel ((1 << DMA_START), &dma->dmastat); - - /* recover from previous short read; erratum 0112 workaround #1 */ - if (clear_nak) - writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp); + start_queue (ep, tmp, req->td_dma); } static inline void @@ -893,7 +928,6 @@ _req->status = -EINPROGRESS; _req->actual = 0; - req->dma_done = 0; /* kickstart this i/o queue? */ if (list_empty (&ep->queue) && !ep->stopped) { @@ -977,10 +1011,11 @@ ) { req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount); - rmb (); done (ep, req, status); } +static void restart_dma (struct net2280_ep *ep); + static void scan_dma_completions (struct net2280_ep *ep) { /* only look at descriptors that were "naturally" retired, @@ -1000,14 +1035,37 @@ break; /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short" - * packets, including overruns, even when the transfer was - * exactly the length requested (dmacount now zero). - * FIXME there's an overrun case here too, where we expect - * a short packet but receive a max length one (won't NAK). + * cases where DMA must be aborted; this code handles + * all non-abort DMA completions. */ - if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) { - req->dma_done = 1; + if (unlikely (req->td->dmadesc == 0)) { + /* paranoia */ + tmp = readl (&ep->dma->dmacount); + if (tmp & DMA_BYTE_COUNT_MASK) + break; + /* single transfer mode */ + dma_done (ep, req, tmp, 0); break; + } else if (!ep->is_in + && (req->req.length % ep->ep.maxpacket) != 0) { + tmp = readl (&ep->regs->ep_stat); + + /* AVOID TROUBLE HERE by not issuing short reads from + * your gadget driver. That helps avoids errata 0121, + * 0122, and 0124; not all cases trigger the warning. + */ + if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) { + WARN (ep->dev, "%s lost packet sync!\n", + ep->ep.name); + req->req.status = -EOVERFLOW; + } else if ((tmp = readl (&ep->regs->ep_avail)) != 0) { + /* fifo gets flushed later */ + ep->out_overflow = 1; + DEBUG (ep->dev, "%s dma, discard %d len %d\n", + ep->ep.name, tmp, + req->req.length); + req->req.status = -EOVERFLOW; + } } dma_done (ep, req, tmp, 0); } @@ -1016,41 +1074,50 @@ static void restart_dma (struct net2280_ep *ep) { struct net2280_request *req; + u32 dmactl = dmactl_default; if (ep->stopped) return; req = list_entry (ep->queue.next, struct net2280_request, queue); -#ifdef USE_DMA_CHAINING + if (!use_dma_chaining) { + start_dma (ep, req); + return; + } + /* the 2280 will be processing the queue unless queue hiccups after * the previous transfer: * IN: wanted automagic zlp, head doesn't (or vice versa) + * DMA_FIFO_VALIDATE doesn't init from dma descriptors. * OUT: was "usb-short", we must restart. */ - if (!req->valid) { + if (ep->is_in && !req->valid) { struct net2280_request *entry, *prev = 0; - int qmode, reqmode, done = 0; + int reqmode, done = 0; DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td); - qmode = likely (req->req.zero + ep->in_fifo_validate = likely (req->req.zero || (req->req.length % ep->ep.maxpacket) != 0); + if (ep->in_fifo_validate) + dmactl |= (1 << DMA_FIFO_VALIDATE); list_for_each_entry (entry, &ep->queue, queue) { u32 dmacount; - if (entry != req) + if (entry == req) continue; dmacount = entry->td->dmacount; if (!done) { reqmode = likely (entry->req.zero || (entry->req.length % ep->ep.maxpacket) != 0); - if (reqmode == qmode) { + if (reqmode == ep->in_fifo_validate) { entry->valid = 1; dmacount |= valid_bit; entry->td->dmacount = dmacount; prev = entry; continue; } else { + /* force a hiccup */ prev->td->dmacount |= dma_done_ie; done = 1; } @@ -1062,22 +1129,21 @@ entry->td->dmacount = dmacount; prev = entry; } - start_dma (ep, req); - } else if (!ep->is_in - && (readl (&ep->regs->ep_stat) - & (1 << NAK_OUT_PACKETS)) != 0) - start_dma (ep, req); -#else - start_dma (ep, req); -#endif + } + + writel (0, &ep->dma->dmactl); + start_queue (ep, dmactl, req->td_dma); } -static inline void abort_dma (struct net2280_ep *ep) +static void abort_dma (struct net2280_ep *ep) { /* abort the current transfer */ - writel ((1 << DMA_ABORT), &ep->dma->dmastat); - - /* collect completed transfers (except the current one) */ + if (likely (!list_empty (&ep->queue))) { + /* FIXME work around errata 0121, 0122, 0124 */ + writel ((1 << DMA_ABORT), &ep->dma->dmastat); + spin_stop_dma (ep->dma); + } else + stop_dma (ep->dma); scan_dma_completions (ep); } @@ -1108,43 +1174,53 @@ int stopped; ep = container_of (_ep, struct net2280_ep, ep); - req = container_of (_req, struct net2280_request, req); if (!_ep || (!ep->desc && ep->num != 0) || !_req) return -EINVAL; spin_lock_irqsave (&ep->dev->lock, flags); stopped = ep->stopped; - /* pause dma while we scan the queue */ + /* quiesce dma while we patch the queue */ dmactl = 0; ep->stopped = 1; if (ep->dma) { dmactl = readl (&ep->dma->dmactl); - writel (dmactl & ~(1 << DMA_ENABLE), &ep->dma->dmactl); - /* force synch, clean any completed requests */ - spin_stop_dma (ep->dma); + /* WARNING erratum 0127 may kick in ... */ + stop_dma (ep->dma); scan_dma_completions (ep); } + /* make sure it's still queued on this endpoint */ + list_for_each_entry (req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) { + spin_unlock_irqrestore (&ep->dev->lock, flags); + return -EINVAL; + } + /* queue head may be partially complete. */ if (ep->queue.next == &req->queue) { if (ep->dma) { DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name); _req->status = -ECONNRESET; abort_dma (ep); - if (likely (ep->queue.next == &req->queue)) + if (likely (ep->queue.next == &req->queue)) { + // NOTE: misreports single-transfer mode + req->td->dmacount = 0; /* invalidate */ dma_done (ep, req, - le32_to_cpup (&req->td->dmacount), + readl (&ep->dma->dmacount), -ECONNRESET); + } } else { DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name); done (ep, req, -ECONNRESET); } req = 0; -#ifdef USE_DMA_CHAINING /* patch up hardware chaining data */ - } else if (ep->dma) { + } else if (ep->dma && use_dma_chaining) { if (req->queue.prev == ep->queue.next) { writel (le32_to_cpu (req->td->dmadesc), &ep->dma->dmadesc); @@ -1161,7 +1237,6 @@ if (req->td->dmacount & dma_done_ie) prev->td->dmacount |= dma_done_ie; } -#endif } if (req) @@ -1188,10 +1263,14 @@ /*-------------------------------------------------------------------------*/ +static int net2280_fifo_status (struct usb_ep *_ep); + static int net2280_set_halt (struct usb_ep *_ep, int value) { struct net2280_ep *ep; + unsigned long flags; + int retval = 0; ep = container_of (_ep, struct net2280_ep, ep); if (!_ep || (!ep->desc && ep->num != 0)) @@ -1202,19 +1281,27 @@ == USB_ENDPOINT_XFER_ISOC) return -EINVAL; - VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); - - /* set/clear, then synch memory views with the device */ - if (value) { - if (ep->num == 0) - ep->dev->protocol_stall = 1; - else - set_halt (ep); - } else - clear_halt (ep); - (void) readl (&ep->regs->ep_rsp); + spin_lock_irqsave (&ep->dev->lock, flags); + if (!list_empty (&ep->queue)) + retval = -EAGAIN; + else if (ep->is_in && value && net2280_fifo_status (_ep) != 0) + retval = -EAGAIN; + else { + VDEBUG (ep->dev, "%s %s halt\n", _ep->name, + value ? "set" : "clear"); + /* set/clear, then synch memory views with the device */ + if (value) { + if (ep->num == 0) + ep->dev->protocol_stall = 1; + else + set_halt (ep); + } else + clear_halt (ep); + (void) readl (&ep->regs->ep_rsp); + } + spin_unlock_irqrestore (&ep->dev->lock, flags); - return 0; + return retval; } static int @@ -1290,21 +1377,49 @@ static int net2280_wakeup (struct usb_gadget *_gadget) { struct net2280 *dev; + u32 tmp; + unsigned long flags; if (!_gadget) return 0; dev = container_of (_gadget, struct net2280, gadget); - writel (1 << GENERATE_RESUME, &dev->usb->usbstat); + + spin_lock_irqsave (&dev->lock, flags); + tmp = readl (&dev->usb->usbctl); + if (tmp & (1 << DEVICE_REMOTE_WAKEUP_ENABLE)) + writel (1 << GENERATE_RESUME, &dev->usb->usbstat); + spin_unlock_irqrestore (&dev->lock, flags); /* pci writes may still be posted */ return 0; } +static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value) +{ + struct net2280 *dev; + u32 tmp; + unsigned long flags; + + if (!_gadget) + return 0; + dev = container_of (_gadget, struct net2280, gadget); + + spin_lock_irqsave (&dev->lock, flags); + tmp = readl (&dev->usb->usbctl); + if (value) + tmp |= (1 << SELF_POWERED_STATUS); + else + tmp &= ~(1 << SELF_POWERED_STATUS); + writel (tmp, &dev->usb->usbctl); + spin_unlock_irqrestore (&dev->lock, flags); + + return 0; +} + static const struct usb_gadget_ops net2280_ops = { .get_frame = net2280_get_frame, .wakeup = net2280_wakeup, - - // .set_selfpowered = net2280_set_selfpowered, + .set_selfpowered = net2280_set_selfpowered, }; /*-------------------------------------------------------------------------*/ @@ -1348,11 +1463,14 @@ /* Main Control Registers */ t = snprintf (next, size, "%s version " DRIVER_VERSION - ", chiprev %04x\n" + ", chiprev %04x, dma %s\n\n" "devinit %03x fifoctl %08x gadget '%s'\n" "pci irqenb0 %02x irqenb1 %08x " "irqstat0 %04x irqstat1 %08x\n", driver_name, dev->chiprev, + use_dma + ? (use_dma_chaining ? "chaining" : "enabled") + : "disabled", readl (&dev->regs->devinit), readl (&dev->regs->fifoctl), s, @@ -1399,7 +1517,7 @@ t1 = readl (&ep->regs->ep_cfg); t2 = readl (&ep->regs->ep_rsp) & 0xff; t = snprintf (next, size, - "%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s" + "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s" "irqenb %02x\n", ep->ep.name, t1, t2, (t2 & (1 << CLEAR_NAK_OUT_PACKETS)) @@ -1453,7 +1571,7 @@ // none yet /* Statistics */ - t = snprintf (next, size, "irqs: "); + t = snprintf (next, size, "\nirqs: "); size -= t; next += t; for (i = 0; i < 7; i++) { @@ -1462,7 +1580,7 @@ ep = &dev->ep [i]; if (i && !ep->irqs) continue; - t = snprintf (next, size, " %s/%ld", ep->ep.name, ep->irqs); + t = snprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs); size -= t; next += t; @@ -1504,7 +1622,7 @@ continue; t = d->bEndpointAddress; t = snprintf (next, size, - "%s (ep%d%s-%s) max %04x %s\n", + "\n%s (ep%d%s-%s) max %04x %s fifo %d\n", ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK, (t & USB_DIR_IN) ? "in" : "out", ({ char *val; @@ -1517,7 +1635,7 @@ val = "iso"; break; }; val; }), le16_to_cpu (d->wMaxPacketSize) & 0x1fff, - ep->dma ? "dma" : "pio" + ep->dma ? "dma" : "pio", ep->fifo_size ); } else /* ep0 should only have one transfer queued */ t = snprintf (next, size, "ep0 max 64 pio %s\n", @@ -1552,6 +1670,20 @@ goto done; size -= t; next += t; + + if (ep->dma) { + struct net2280_dma *td; + + td = req->td; + t = snprintf (next, size, "\t td %08x " + " count %08x buf %08x desc %08x\n", + req->td_dma, td->dmacount, + td->dmaaddr, td->dmadesc); + if (t <= 0 || t > size) + goto done; + size -= t; + next += t; + } } } @@ -1686,8 +1818,10 @@ /* clear old dma and irq state */ for (tmp = 0; tmp < 4; tmp++) { - writel ((1 << DMA_ABORT), &dev->dma [tmp].dmastat); - stop_dma (&dev->dma [tmp]); + struct net2280_ep *ep = &dev->ep [tmp + 1]; + + if (ep->dma) + abort_dma (ep); } writel (~0, &dev->regs->irqstat0), writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1), @@ -1767,7 +1901,7 @@ | (1 << SELF_POWERED_USB_DEVICE) | (1 << REMOTE_WAKEUP_SUPPORT) | (1 << USB_DETECT_ENABLE) - | (1 << DEVICE_REMOTE_WAKEUP_ENABLE) + | (1 << SELF_POWERED_STATUS) , &dev->usb->usbctl); /* enable irqs so we can see ep0 and general operation */ @@ -1889,6 +2023,7 @@ spin_unlock_irqrestore (&dev->lock, flags); driver->unbind (&dev->gadget); + dev->gadget.dev.driver = 0; dev->driver = 0; net2280_led_active (dev, 0); @@ -1947,6 +2082,8 @@ ep->stopped = 1; set_halt (ep); } + if (!req) + allow_status (ep); mode = 2; /* reply to extra IN data tokens with a zlp */ } else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) { @@ -1987,41 +2124,62 @@ if (likely (ep->dma != 0)) { if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) { u32 count; + int stopped = ep->stopped; /* TRANSFERRED works around OUT_DONE erratum 0112. * we expect (N <= maxpacket) bytes; host wrote M. * iff (M < N) we won't ever see a DMA interrupt. */ - count = readl (&ep->dma->dmacount); - count &= DMA_BYTE_COUNT_MASK; - if (!req->dma_done) { - /* dma can finish with the FIFO non-empty, - * on (M > N) errors. + ep->stopped = 1; + for (count = 0; ; t = readl (&ep->regs->ep_stat)) { + + /* any preceding dma transfers must finish. + * dma handles (M >= N), may empty the queue + */ + scan_dma_completions (ep); + if (unlikely (list_empty (&ep->queue) + || ep->out_overflow)) { + req = 0; + break; + } + req = list_entry (ep->queue.next, + struct net2280_request, queue); + + /* here either (M < N), a "real" short rx; + * or (M == N) and the queue didn't empty */ - while (count && (t & (1 << FIFO_EMPTY)) == 0) { - cpu_relax (); - t = readl (&ep->regs->ep_stat); + if (likely (t & (1 << FIFO_EMPTY))) { count = readl (&ep->dma->dmacount); count &= DMA_BYTE_COUNT_MASK; + if (readl (&ep->dma->dmadesc) + != req->td_dma) + req = 0; + break; } + udelay(1); } /* stop DMA, leave ep NAKing */ writel ((1 << DMA_ABORT), &ep->dma->dmastat); spin_stop_dma (ep->dma); - /* buffer might have been too small */ - t = readl (&ep->regs->ep_avail); - if (t != 0) - DEBUG (ep->dev, "%s dma, discard %d len %d\n", - ep->ep.name, t, count); - dma_done (ep, req, count, t ? -EOVERFLOW : 0); + if (likely (req)) { + req->td->dmacount = 0; + t = readl (&ep->regs->ep_avail); + dma_done (ep, req, count, t); + } /* also flush to prevent erratum 0106 trouble */ - if (t || ep->dev->chiprev == 0x0100) + if (unlikely (ep->out_overflow + || (ep->dev->chiprev == 0x0100 + && ep->dev->gadget.speed + == USB_SPEED_FULL))) { out_flush (ep); + ep->out_overflow = 0; + } - /* restart dma (still NAKing OUT!) if needed */ + /* (re)start dma if needed, stop NAKing */ + ep->stopped = stopped; if (!list_empty (&ep->queue)) restart_dma (ep); } else @@ -2192,11 +2350,12 @@ * that'll mean a lot less irqs for some drivers. */ ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0; - if (ep->is_in) + if (ep->is_in) { scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT) | (1 << DATA_OUT_PING_TOKEN_INTERRUPT) | (1 << DATA_IN_TOKEN_INTERRUPT); - else + stop_out_naking (ep); + } else scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT) | (1 << DATA_OUT_PING_TOKEN_INTERRUPT) | (1 << DATA_IN_TOKEN_INTERRUPT); @@ -2398,18 +2557,18 @@ tmp = readl (&dma->dmastat); writel (tmp, &dma->dmastat); -#ifdef USE_DMA_CHAINING - /* chaining should stop only on error (which?) + /* chaining should stop on abort, short OUT from fifo, * or (stat0 codepath) short OUT transfer. */ -#else - if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT)) == 0) { - DEBUG (ep->dev, "%s no xact done? %08x\n", - ep->ep.name, tmp); - continue; + if (!use_dma_chaining) { + if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT)) + == 0) { + DEBUG (ep->dev, "%s no xact done? %08x\n", + ep->ep.name, tmp); + continue; + } + stop_dma (ep->dma); } - stop_dma (ep->dma); -#endif /* OUT transfers terminate when the data from the * host is in our memory. Process whatever's done. @@ -2425,16 +2584,14 @@ /* disable dma on inactive queues; else maybe restart */ if (list_empty (&ep->queue)) { -#ifdef USE_DMA_CHAINING - stop_dma (ep->dma); -#endif + if (use_dma_chaining) + stop_dma (ep->dma); } else { tmp = readl (&dma->dmactl); - if ((tmp & (1 << DMA_SCATTER_GATHER_ENABLE)) == 0 + if (!use_dma_chaining || (tmp & (1 << DMA_ENABLE)) == 0) restart_dma (ep); -#ifdef USE_DMA_CHAINING - else if (ep->desc->bEndpointAddress & USB_DIR_IN) { + else if (ep->is_in && use_dma_chaining) { struct net2280_request *req; u32 dmacount; @@ -2449,12 +2606,9 @@ dmacount &= __constant_cpu_to_le32 ( (1 << VALID_BIT) | DMA_BYTE_COUNT_MASK); - if (dmacount && (dmacount & valid_bit) == 0) { - stop_dma (ep->dma); + if (dmacount && (dmacount & valid_bit) == 0) restart_dma (ep); - } } -#endif } ep->irqs++; } @@ -2505,7 +2659,7 @@ /* tear down the binding between this driver and the pci device */ -static void net2280_remove (struct pci_dev *pdev) +static void __exit net2280_remove (struct pci_dev *pdev) { struct net2280 *dev = pci_get_drvdata (pdev); @@ -2665,12 +2819,14 @@ } td->dmacount = 0; /* not VALID */ td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmadesc = td->dmaaddr; dev->ep [i].dummy = td; } /* enable lower-overhead pci memory bursts during DMA */ - writel ((1 << PCI_RETRY_ABORT_ENABLE) - | (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) + writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) + // 256 write retries may not be enough... + // | (1 << PCI_RETRY_ABORT_ENABLE) | (1 << DMA_READ_MULTIPLE_ENABLE) | (1 << DMA_READ_LINE_ENABLE) , &dev->pci->pcimstctl); @@ -2686,15 +2842,10 @@ INFO (dev, "%s\n", driver_desc); INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", bufp, base, dev->chiprev); - bufp = DRIVER_VERSION -#ifndef USE_DMA_CHAINING - " (no dma chain)" -#endif -#ifdef NET2280_DMA_OUT_WORKAROUND - " (no dma out)" -#endif - ; - INFO (dev, "version: %s\n", bufp); + INFO (dev, "version: " DRIVER_VERSION "; dma %s\n", + use_dma + ? (use_dma_chaining ? "chaining" : "enabled") + : "disabled"); the_controller = dev; device_register (&dev->gadget.dev); @@ -2729,7 +2880,7 @@ .id_table = pci_ids, .probe = net2280_probe, - .remove = net2280_remove, + .remove = __exit_p(net2280_remove), /* FIXME add power management support */ }; @@ -2740,6 +2891,8 @@ static int __init init (void) { + if (!use_dma) + use_dma_chaining = 0; return pci_module_init (&net2280_pci_driver); } module_init (init); diff -urN linux-2.6.2-rc2/drivers/usb/gadget/net2280.h linux-2.6.2-rc3/drivers/usb/gadget/net2280.h --- linux-2.6.2-rc2/drivers/usb/gadget/net2280.h 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/net2280.h 2004-01-30 18:49:23.000000000 -0800 @@ -520,6 +520,7 @@ unsigned num : 8, fifo_size : 12, in_fifo_validate : 1, + out_overflow : 1, stopped : 1, is_in : 1, is_iso : 1; @@ -529,6 +530,7 @@ { /* ep0 only */ writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) + | (1 << CLEAR_NAK_OUT_PACKETS) | (1 << CLEAR_NAK_OUT_PACKETS_MODE) , &ep->regs->ep_rsp); ep->stopped = 1; @@ -546,7 +548,6 @@ dma_addr_t td_dma; struct list_head queue; unsigned mapped : 1, - dma_done : 1, valid : 1; }; @@ -559,8 +560,7 @@ unsigned enabled : 1, protocol_stall : 1, got_irq : 1, - region : 1, - selfpowered : 1; + region : 1; u16 chiprev; /* pci state used to access those endpoints */ diff -urN linux-2.6.2-rc2/drivers/usb/gadget/serial.c linux-2.6.2-rc3/drivers/usb/gadget/serial.c --- linux-2.6.2-rc2/drivers/usb/gadget/serial.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/serial.c 2004-01-30 18:49:23.000000000 -0800 @@ -135,9 +135,6 @@ #define GS_NUM_PORTS 16 -#define GS_VENDOR_ID 0x05F9 -#define GS_PRODUCT_ID 0xFFFF - #define GS_NUM_CONFIGS 1 #define GS_NO_CONFIG_ID 0 #define GS_BULK_CONFIG_ID 2 @@ -187,7 +184,7 @@ * DMA channels to manage their FIFOs. It supports high speed. * Those endpoints can be arranged in any desired configuration. */ -#ifdef CONFIG_USB_G_SERIAL_NET2280 +#ifdef CONFIG_USB_GADGET_NET2280 #define CHIP "net2280" #define EP0_MAXPACKET 64 static const char EP_OUT_NAME[] = "ep-a"; @@ -220,13 +217,13 @@ * can't use altsettings or reset the interfaces independently. * So stick to a single interface. */ -#ifdef CONFIG_USB_G_SERIAL_PXA2XX +#ifdef CONFIG_USB_GADGET_PXA2XX #define CHIP "pxa2xx" #define EP0_MAXPACKET 16 -static const char EP_OUT_NAME[] = "ep12out-bulk"; -#define EP_OUT_NUM 12 -static const char EP_IN_NAME[] = "ep11in-bulk"; -#define EP_IN_NUM 11 +static const char EP_OUT_NAME[] = "ep2out-bulk"; +#define EP_OUT_NUM 2 +static const char EP_IN_NAME[] = "ep1in-bulk"; +#define EP_IN_NUM 1 #define SELFPOWER USB_CONFIG_ATT_SELFPOWER /* no hw optimizations to apply */ @@ -245,7 +242,7 @@ * in special situations. So this is a case of "choose it right * during enumeration" ... */ -#ifdef CONFIG_USB_G_SERIAL_SA1100 +#ifdef CONFIG_USB_GADGET_SA1100 #define CHIP "sa1100" #define EP0_MAXPACKET 8 static const char EP_OUT_NAME[] = "ep1out-bulk"; @@ -264,7 +261,7 @@ * * This has three semi-configurable full speed bulk/interrupt endpoints. */ -#ifdef CONFIG_USB_G_SERIAL_GOKU +#ifdef CONFIG_USB_GADGET_GOKU #define CHIP "goku" #define DRIVER_VERSION_NUM 0x0116 #define EP0_MAXPACKET 8 @@ -302,6 +299,14 @@ /* else value must be USB_CONFIG_ATT_WAKEUP */ #endif +/* Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. + */ +#define GS_VENDOR_ID 0x0525 /* NetChip */ +#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */ + /* Structures */ diff -urN linux-2.6.2-rc2/drivers/usb/gadget/zero.c linux-2.6.2-rc3/drivers/usb/gadget/zero.c --- linux-2.6.2-rc2/drivers/usb/gadget/zero.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/gadget/zero.c 2004-01-30 18:49:23.000000000 -0800 @@ -131,7 +131,7 @@ * DMA channels to manage their FIFOs. It supports high speed. * Those endpoints can be arranged in any desired configuration. */ -#ifdef CONFIG_USB_ZERO_NET2280 +#if defined(CONFIG_USB_GADGET_NET2280) || defined(CONFIG_USB_GADGET_DUMMY_HCD) #define CHIP "net2280" #define DRIVER_VERSION_NUM 0x0101 static const char EP_OUT_NAME [] = "ep-a"; @@ -154,7 +154,7 @@ * can't use altsettings or reset the interfaces independently. * So stick to a single interface. */ -#ifdef CONFIG_USB_ZERO_PXA2XX +#ifdef CONFIG_USB_GADGET_PXA2XX #define CHIP "pxa2xx" #define DRIVER_VERSION_NUM 0x0103 static const char EP_OUT_NAME [] = "ep12out-bulk"; @@ -176,7 +176,7 @@ * in special situations. So this is a case of "choose it right * during enumeration" ... */ -#ifdef CONFIG_USB_ZERO_SA1100 +#ifdef CONFIG_USB_GADGET_SA1100 #define CHIP "sa1100" #define DRIVER_VERSION_NUM 0x0105 static const char EP_OUT_NAME [] = "ep1out-bulk"; @@ -192,7 +192,7 @@ * * This has three semi-configurable full speed bulk/interrupt endpoints. */ -#ifdef CONFIG_USB_ZERO_GOKU +#ifdef CONFIG_USB_GADGET_GOKU #define CHIP "goku" #define DRIVER_VERSION_NUM 0x0106 static const char EP_OUT_NAME [] = "ep1-bulk"; @@ -936,7 +936,7 @@ if (number == dev->config) return 0; -#ifdef CONFIG_USB_ZERO_SA1100 +#ifdef CONFIG_USB_GADGET_SA1100 if (dev->config) { /* tx fifo is full, but we can't clear it...*/ INFO (dev, "can't change configurations\n"); diff -urN linux-2.6.2-rc2/drivers/usb/host/ohci-hcd.c linux-2.6.2-rc3/drivers/usb/host/ohci-hcd.c --- linux-2.6.2-rc2/drivers/usb/host/ohci-hcd.c 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/host/ohci-hcd.c 2004-01-30 18:49:23.000000000 -0800 @@ -684,6 +684,10 @@ #include "ohci-sa1111.c" #endif -#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111)) +#ifdef CONFIG_ARCH_OMAP +#include "ohci-omap.c" +#endif + +#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111) || defined(CONFIG_ARCH_OMAP)) #error "missing bus glue for ohci-hcd" #endif diff -urN linux-2.6.2-rc2/drivers/usb/host/ohci-omap.c linux-2.6.2-rc3/drivers/usb/host/ohci-omap.c --- linux-2.6.2-rc2/drivers/usb/host/ohci-omap.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/host/ohci-omap.c 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,673 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2002 Hewlett-Packard Company + * + * OMAP Bus Glue + * + * Written by Christopher Hoover + * Based on fragments of previous driver by Rusell King et al. + * + * Modified for OMAP from ohci-sa1111.c by Tony Lindgren + * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc. + * + * This file is licenced under the GPL. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ohci-omap.h" + +#ifndef CONFIG_ARCH_OMAP +#error "This file is OMAP bus glue. CONFIG_OMAP must be defined." +#endif + +extern int usb_disabled(void); +extern int ocpi_enable(void); + +/* + * Use the first port only by default. Override with hmc_mode option. + * + * NOTE: Many OMAP-1510 Innovators supposedly have bad wiring for the USB ports + * 1 & 2, so only port 0 will work. To use the OHCI on the first port, use + * the Innovator USB client cable with a client-to-client connector and modify + * either the cable or the hub to feed 5V VBUS back to Innovator. VBUS should + * be the red lead in the cable. + * + * To mount USB hard disk as root, see the patch for do_mounts.c that tries + * remounting the root, and use root=0801 if your root is on sda1. Does not + * work with devfs. + */ +static int default_hmc_mode = 16; +static int hmc_mode = 1234; + +/* + * Set the USB host pin multiplexing and the selected HMC mode + */ +static int omap_usb_set_hmc_mode(int hmc_mode) +{ + unsigned int val; + + switch (hmc_mode) { + case 0: + /* 0: function, 1: disabled, 2: disabled */ + omap_cfg_reg(W4_USB_PUEN); + omap_cfg_reg(R18_1510_USB_GPIO0); + break; + case 4: + /* 0: function 1: host 2: host */ + omap_cfg_reg(usb1_speed); + omap_cfg_reg(usb1_susp); + omap_cfg_reg(usb1_seo); + omap_cfg_reg(usb1_txen); + omap_cfg_reg(usb1_txd); + omap_cfg_reg(usb1_vp); + omap_cfg_reg(usb1_vm); + omap_cfg_reg(usb1_rcv); + omap_cfg_reg(usb2_susp); + omap_cfg_reg(usb2_seo); + omap_cfg_reg(usb2_txen); + omap_cfg_reg(usb2_txd); + omap_cfg_reg(usb2_vp); + omap_cfg_reg(usb2_vm); + omap_cfg_reg(usb2_rcv); + break; + case 16: + /* 0: host, 1: disabled, 2: disabled */ + omap_cfg_reg(W9_USB0_TXEN); + omap_cfg_reg(AA9_USB0_VP); + omap_cfg_reg(Y5_USB0_RCV); + omap_cfg_reg(R9_USB0_VM); + omap_cfg_reg(V6_USB0_TXD); + omap_cfg_reg(W5_USB0_SE0); + break; + default: + printk("Unknown USB host configuration: %i\n", hmc_mode); + return -ENODEV; + } + + /* Write the selected HMC mode */ + val = readl(MOD_CONF_CTRL_0) & ~HMC_CLEAR; + val |= (hmc_mode << 1); + writel(val, MOD_CONF_CTRL_0); + + return 0; +} + +/* + * OHCI clock initialization for OMAP-1510 and 1610 + */ +static int omap_ohci_clock_power(int on) +{ + if (on) { + if (cpu_is_omap_1510()) { + /* Use DPLL, not APLL */ + writel(readl(ULPD_APLL_CTRL_REG) & ~APLL_NDPLL_SWITCH, + ULPD_APLL_CTRL_REG); + + /* Enable DPLL */ + writel(readl(ULPD_DPLL_CTRL_REG) | DPLL_PLL_ENABLE, + ULPD_DPLL_CTRL_REG); + + /* Software request for USB 48MHz clock */ + writel(readl(ULPD_SOFT_REQ_REG) | SOFT_REQ_REG_REQ, + ULPD_SOFT_REQ_REG); + + while (!(readl(ULPD_DPLL_CTRL_REG) & DPLL_LOCK)); + } + + if (cpu_is_omap_1610()) { + /* Enable OHCI */ + writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_OTG_REQ, + ULPD_SOFT_REQ_REG); + + /* USB host clock request if not using OTG */ + writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ, + ULPD_SOFT_REQ_REG); + + outl(inl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ, + ULPD_STATUS_REQ_REG); + } + + /* Enable 48MHz clock to USB */ + writel(readl(ULPD_CLOCK_CTRL_REG) | USB_MCLK_EN, + ULPD_CLOCK_CTRL_REG); + + writel(readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK), + ARM_IDLECT2); + + writel(readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN, + MOD_CONF_CTRL_0); + } else { + /* Disable 48MHz clock to USB */ + writel(readl(ULPD_CLOCK_CTRL_REG) & ~USB_MCLK_EN, + ULPD_CLOCK_CTRL_REG); + + /* FIXME: The DPLL stays on for now */ + } + + return 0; +} + +/* + * Hardware specific transceiver power on/off + */ +static int omap_ohci_transceiver_power(int on) +{ + if (on) { + if (omap_is_innovator()) + writel(readl(OMAP1510_FPGA_HOST_CTRL) | 0x20, + OMAP1510_FPGA_HOST_CTRL); + } else { + if (omap_is_innovator()) + writel(readl(OMAP1510_FPGA_HOST_CTRL) & ~0x20, + OMAP1510_FPGA_HOST_CTRL); + } + + return 0; +} + +/* + * OMAP-1510 specific Local Bus clock on/off + */ +static int omap_1510_local_bus_power(int on) +{ + if (on) { + writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL); + udelay(200); + } else { + writel(0, OMAP1510_LB_MMU_CTL); + } + + return 0; +} + +/* + * OMAP-1510 specific Local Bus initialization + * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE. + * See also arch/mach-omap/memory.h for __virt_to_bus() and + * __bus_to_virt() which need to match with the physical + * Local Bus address below. + */ +static int omap_1510_local_bus_init(void) +{ + unsigned int tlb; + unsigned long lbaddr, physaddr; + + writel((readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, + OMAP1510_LB_CLOCK_DIV); + + /* Configure the Local Bus MMU table */ + for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) { + lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET; + physaddr = tlb * 0x00100000 + PHYS_OFFSET; + writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H); + writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, + OMAP1510_LB_MMU_CAM_L); + writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H); + writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L); + writel(tlb << 4, OMAP1510_LB_MMU_LCK); + writel(0x1, OMAP1510_LB_MMU_LD_TLB); + } + + /* Enable the walking table */ + writel(readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL); + udelay(200); + + return 0; +} + +/* + * OMAP-1610 specific hardware initialization + * + * Intended to configure OMAP-1610 USB host and OTG ports depending on + * the HMC mode selected. + * + * FIXME: Currently only supports alternate ping group 2 mode, should + * be easy to modify for other configurations once there is some + * hardware to test with. + */ +static int omap_1610_usb_init(int mode) +{ + u_int val = 0; + + /* Configure the OMAP transceiver settings */ + val |= (1 << 8); /* CONF_USB2_UNI TRM p 15-205*/ + val |= (4 << 4); /* TRM p 5-59, p 15-157 (1224) */ + + //val |= (1 << 3); /* Isolate integrated transceiver from port 0 */ + val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */ + val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */ + + outl(val, USB_TRANSCEIVER_CTRL); + + /* Set the USB0_TRX_MODE */ + val = 0; + val &= ~OTG_IDLE_EN; + val &= ~DEV_IDLE_EN; + val &= ~(7 << 16); /* Clear USB0_TRX_MODE */ + val |= (3 << 16); /* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */ + outl(val, OTG_SYSCON_1); + + /* + * Control via OTG, see TRM p 15-163 + */ + val = 0; + //val |= 1; /* REVISIT: Enable OTG = 1 */ + + /* Control via OTG */ + val &= ~HMC_PADEN; + val &= ~OTG_PADEN; + val |= UHOST_EN; + + val &= ~0x3f; /* Clear HMC mode */ + val |= mode; /* Set HMC mode */ + val &= ~(7 << 16); /* Clear ASE0_BRST */ + val |= (4 << 16); /* Must be 4 */ + val |= USBX_SYNCHRO; /* Must be set */ + val |= SRP_VBUS; + outl(val, OTG_SYSCON_2); + + /* Enable OTG idle */ + //outl(inl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static void omap_start_hc(struct omap_dev *dev) +{ + printk(KERN_DEBUG __FILE__ + ": starting OMAP OHCI USB Controller\n"); + + /* + * Set the HMC mode for the USB ports + */ +#if 0 + /* See note about the Innovator wiring above */ + if (omap_is_innovator()) + hmc_mode = 4; /* 0: function 1: host 2: host */ +#endif + + if (cpu_is_omap_1610()) + ocpi_enable(); + + omap_usb_set_hmc_mode(hmc_mode); + + omap_ohci_clock_power(1); + omap_ohci_transceiver_power(1); + + if (cpu_is_omap_1510()) { + omap_1510_local_bus_power(1); + omap_1510_local_bus_init(); + } + + if (cpu_is_omap_1610()) + omap_1610_usb_init(hmc_mode); + + //omap_enable_device(dev); +} + +static void omap_stop_hc(struct omap_dev *dev) +{ + printk(KERN_DEBUG __FILE__ + ": stopping OMAP OHCI USB Controller\n"); + + /* + * FIXME: Put the USB host controller into reset. + */ + + /* + * FIXME: Stop the USB clock. + */ + //omap_disable_device(dev); + +} + + +/*-------------------------------------------------------------------------*/ + +static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r) +{ + struct usb_hcd *hcd = __hcd; + + return usb_hcd_irq(irq, hcd, r); +} + +/*-------------------------------------------------------------------------*/ + +void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *); + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + + +/** + * usb_hcd_omap_probe - initialize OMAP-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + * Store this function in the HCD's struct pci_driver as probe(). + */ +int usb_hcd_omap_probe (const struct hc_driver *driver, + struct usb_hcd **hcd_out, + struct omap_dev *dev) +{ + int retval; + struct usb_hcd *hcd = 0; + + if (!request_mem_region(dev->res.start, + dev->res.end - dev->res.start + 1, hcd_name)) { + dbg("request_mem_region failed"); + return -EBUSY; + } + + omap_start_hc(dev); + + hcd = driver->hcd_alloc (); + if (hcd == NULL){ + dbg ("hcd_alloc failed"); + retval = -ENOMEM; + goto err1; + } + + hcd->driver = (struct hc_driver *) driver; + hcd->description = driver->description; + hcd->irq = dev->irq[0]; + hcd->regs = dev->mapbase; + hcd->pdev = OMAP_FAKE_PCIDEV; + hcd->self.controller = &dev->dev; + hcd->controller = hcd->self.controller; + + retval = hcd_buffer_create (hcd); + if (retval != 0) { + dbg ("pool alloc fail"); + goto err1; + } + + retval = request_irq (hcd->irq, + usb_hcd_omap_hcim_irq, + SA_INTERRUPT, hcd->description, hcd); + if (retval != 0) { + dbg("request_irq failed"); + retval = -EBUSY; + goto err2; + } + + info ("%s (OMAP) at 0x%p, irq %d\n", + hcd->description, hcd->regs, hcd->irq); + + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; + hcd->self.hcpriv = (void *) hcd; + hcd->self.bus_name = "omap"; + hcd->product_desc = "OMAP OHCI"; + + INIT_LIST_HEAD (&hcd->dev_list); + usb_register_bus (&hcd->self); + + if ((retval = driver->start (hcd)) < 0) + { + usb_hcd_omap_remove(hcd, dev); + return retval; + } + + *hcd_out = hcd; + return 0; + + err2: + hcd_buffer_destroy (hcd); + if (hcd) + driver->hcd_free(hcd); + err1: + omap_stop_hc(dev); + + release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); + + return retval; +} + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_omap_remove - shutdown processing for OMAP-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_omap_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev) +{ + struct usb_device *hub; + void *base; + + info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); + + if (in_interrupt ()) + BUG (); + + hub = hcd->self.root_hub; + hcd->state = USB_STATE_QUIESCING; + + dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); + usb_disconnect (&hub); + + hcd->driver->stop (hcd); + hcd_buffer_destroy (hcd); + hcd->state = USB_STATE_HALT; + + free_irq (hcd->irq, hcd); + + usb_deregister_bus (&hcd->self); + + base = hcd->regs; + hcd->driver->hcd_free (hcd); + + omap_stop_hc(dev); + + release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); +} + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_omap_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if (hcd->pdev) { + ohci->hcca = pci_alloc_consistent (hcd->pdev, + sizeof *ohci->hcca, &ohci->hcca_dma); + if (!ohci->hcca) + return -ENOMEM; + } + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + if ((ret = ohci_mem_init (ohci)) < 0) { + ohci_stop (hcd); + return ret; + } + ohci->regs = hcd->regs; + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; + } + + if (hc_start (ohci) < 0) { + err ("can't start %s", ohci->hcd.self.bus_name); + ohci_stop (hcd); + return -EBUSY; + } + create_debug_files (ohci); + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ohci_omap_hc_driver = { + .description = hcd_name, + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11, + + /* + * basic lifecycle operations + */ + .start = ohci_omap_start, +#ifdef CONFIG_PM + /* suspend: ohci_omap_suspend, -- tbd */ + /* resume: ohci_omap_resume, -- tbd */ +#endif + .stop = ohci_stop, + + /* + * memory lifecycle (except per-request) + */ + .hcd_alloc = ohci_hcd_alloc, + .hcd_free = ohci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +}; + +/*-------------------------------------------------------------------------*/ + +static int ohci_hcd_omap_drv_probe(struct omap_dev *dev) +{ + struct usb_hcd *hcd = NULL; + int ret; + + if (usb_disabled()) + return -ENODEV; + + ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev); + + if (ret == 0) + omap_set_drvdata(dev, hcd); + + return ret; +} + +static int ohci_hcd_omap_drv_remove(struct omap_dev *dev) +{ + struct usb_hcd *hcd = omap_get_drvdata(dev); + + usb_hcd_omap_remove(hcd, dev); + + omap_set_drvdata(dev, NULL); + + return 0; +} + +/* + * Driver definition to register with the OMAP bus + */ +static struct omap_driver ohci_hcd_omap_driver = { + .drv = { + .name = OMAP_OHCI_NAME, + }, + .devid = OMAP_OCP_DEVID_USB, + .busid = OMAP_BUS_OCP, + .clocks = 0, + .probe = ohci_hcd_omap_drv_probe, + .remove = ohci_hcd_omap_drv_remove, +}; + +/* Any dma_mask must be set for OHCI to work */ +static u64 omap_dmamask = 0xffffffffUL; + +/* + * Device definition to match the driver above + */ +static struct omap_dev ohci_hcd_omap_device = { + .name = OMAP_OHCI_NAME, + .devid = OMAP_OCP_DEVID_USB, + .busid = OMAP_BUS_OCP, + .mapbase = (void *)OMAP_OHCI_BASE, + .dma_mask = &omap_dmamask, /* Needed only for OHCI */ + .res = { + .start = OMAP_OHCI_BASE, + .end = OMAP_OHCI_BASE + OMAP_OHCI_SIZE, + }, + .irq = { + INT_OHCI, + }, +}; + +static int __init ohci_hcd_omap_init (void) +{ + int ret; + + dbg (DRIVER_INFO " (OMAP)"); + dbg ("block sizes: ed %d td %d\n", + sizeof (struct ed), sizeof (struct td)); + + if (hmc_mode < 0 || hmc_mode > 25) + hmc_mode = default_hmc_mode; + + /* Register the driver with OMAP bus */ + ret = omap_driver_register(&ohci_hcd_omap_driver); + if (ret != 0) + return -ENODEV; + + /* Register the device with OMAP bus */ + ret = omap_device_register(&ohci_hcd_omap_device); + if (ret != 0) { + omap_driver_unregister(&ohci_hcd_omap_driver); + return -ENODEV; + } + + return ret; +} + +MODULE_PARM(hmc_mode, "hmc_mode"); + +static void __exit ohci_hcd_omap_cleanup (void) +{ + omap_device_unregister(&ohci_hcd_omap_device); + omap_driver_unregister(&ohci_hcd_omap_driver); +} + +module_init (ohci_hcd_omap_init); +module_exit (ohci_hcd_omap_cleanup); diff -urN linux-2.6.2-rc2/drivers/usb/host/ohci-omap.h linux-2.6.2-rc3/drivers/usb/host/ohci-omap.h --- linux-2.6.2-rc2/drivers/usb/host/ohci-omap.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/host/ohci-omap.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,57 @@ +/* + * linux/drivers/usb/host/ohci-omap.h + * + * OMAP OHCI USB controller specific defines + */ + +/* OMAP USB OHCI common defines */ +#define OMAP_OHCI_NAME "omap-ohci" +#define OMAP_OHCI_BASE 0xfffba000 +#define OMAP_OHCI_SIZE 4096 + +#define HMC_CLEAR (0x3f << 1) +#define APLL_NDPLL_SWITCH 0x0001 +#define DPLL_PLL_ENABLE 0x0010 +#define DPLL_LOCK 0x0001 +#define SOFT_REQ_REG_REQ 0x0001 +#define USB_MCLK_EN 0x0010 +#define USB_HOST_HHC_UHOST_EN 0x00000200 +#define SOFT_USB_OTG_REQ (1 << 8) +#define SOFT_USB_REQ (1 << 3) +#define STATUS_REQ_REG 0xfffe0840 +#define USB_HOST_DPLL_REQ (1 << 8) +#define SOFT_DPLL_REQ (1 << 0) + +/* OMAP-1510 USB OHCI defines */ +#define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */ +#define OMAP1510_LB_CLOCK_DIV 0xfffec10c +#define OMAP1510_LB_MMU_CTL 0xfffec208 +#define OMAP1510_LB_MMU_LCK 0xfffec224 +#define OMAP1510_LB_MMU_LD_TLB 0xfffec228 +#define OMAP1510_LB_MMU_CAM_H 0xfffec22c +#define OMAP1510_LB_MMU_CAM_L 0xfffec230 +#define OMAP1510_LB_MMU_RAM_H 0xfffec234 +#define OMAP1510_LB_MMU_RAM_L 0xfffec238 + +/* OMAP-1610 USB OHCI defines */ +#define USB_TRANSCEIVER_CTRL 0xfffe1064 +#define OTG_REV 0xfffb0400 + +#define OTG_SYSCON_1 0xfffb0404 +#define OTG_IDLE_EN (1 << 15) +#define DEV_IDLE_EN (1 << 13) + +#define OTG_SYSCON_2 0xfffb0408 +#define OTG_CTRL 0xfffb040c +#define OTG_IRQ_EN 0xfffb0410 +#define OTG_IRQ_SRC 0xfffb0414 + +#define OTG_EN (1 << 31) +#define USBX_SYNCHRO (1 << 30) +#define SRP_VBUS (1 << 12) +#define OTG_PADEN (1 << 10) +#define HMC_PADEN (1 << 9) +#define UHOST_EN (1 << 8) + +/* Hardware specific defines */ +#define OMAP1510_FPGA_HOST_CTRL 0xe800020c diff -urN linux-2.6.2-rc2/drivers/usb/media/dabusb.c linux-2.6.2-rc3/drivers/usb/media/dabusb.c --- linux-2.6.2-rc2/drivers/usb/media/dabusb.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/media/dabusb.c 2004-01-30 18:49:23.000000000 -0800 @@ -781,17 +781,25 @@ static void dabusb_disconnect (struct usb_interface *intf) { + wait_queue_t __wait; pdabusb_t s = usb_get_intfdata (intf); dbg("dabusb_disconnect"); - + + init_waitqueue_entry(&__wait, current); + usb_set_intfdata (intf, NULL); if (s) { usb_deregister_dev (intf, &dabusb_class); s->remove_pending = 1; wake_up (&s->wait); + add_wait_queue(&s->remove_ok, &__wait); + set_current_state(TASK_UNINTERRUPTIBLE); if (s->state == _started) - sleep_on (&s->remove_ok); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&s->remove_ok, &__wait); + s->usbdev = NULL; s->overruns = 0; } diff -urN linux-2.6.2-rc2/drivers/usb/misc/Kconfig linux-2.6.2-rc3/drivers/usb/misc/Kconfig --- linux-2.6.2-rc2/drivers/usb/misc/Kconfig 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/misc/Kconfig 2004-01-30 18:49:23.000000000 -0800 @@ -6,6 +6,7 @@ config USB_EMI62 tristate "EMI 6|2m USB Audio interface support" + depends on USB ---help--- This driver loads firmware to Emagic EMI 6|2m low latency USB Audio and Midi interface. @@ -20,6 +21,7 @@ config USB_EMI26 tristate "EMI 2|6 USB Audio interface support" + depends on USB ---help--- This driver loads firmware to Emagic EMI 2|6 low latency USB Audio interface. diff -urN linux-2.6.2-rc2/drivers/usb/misc/auerswald.c linux-2.6.2-rc3/drivers/usb/misc/auerswald.c --- linux-2.6.2-rc2/drivers/usb/misc/auerswald.c 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/misc/auerswald.c 2004-01-30 18:49:23.000000000 -0800 @@ -1927,7 +1927,6 @@ { struct usb_device *usbdev = interface_to_usbdev(intf); pauerswald_t cp = NULL; - DECLARE_WAIT_QUEUE_HEAD (wqh); unsigned int u = 0; char *pbuf; int ret; @@ -1975,7 +1974,8 @@ dbg ("Version is %X", cp->version); /* allow some time to settle the device */ - sleep_on_timeout (&wqh, HZ / 3 ); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/3); /* Try to get a suitable textual description of the device */ /* Device name:*/ diff -urN linux-2.6.2-rc2/drivers/usb/misc/tiglusb.c linux-2.6.2-rc3/drivers/usb/misc/tiglusb.c --- linux-2.6.2-rc2/drivers/usb/misc/tiglusb.c 2004-01-08 22:59:04.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/misc/tiglusb.c 2004-01-30 18:49:23.000000000 -0800 @@ -161,7 +161,7 @@ int bytes_to_read = 0; int bytes_read = 0; int result = 0; - char buffer[BULK_RCV_MAX]; + char *buffer; unsigned int pipe; if (*f_pos) @@ -173,6 +173,10 @@ if (!s->dev) return -EIO; + buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count; pipe = usb_rcvbulkpipe (s->dev, 1); @@ -203,6 +207,7 @@ } out: + kfree(buffer); return ret ? ret : bytes_read; } @@ -214,7 +219,7 @@ int bytes_to_write = 0; int bytes_written = 0; int result = 0; - char buffer[BULK_SND_MAX]; + char *buffer; unsigned int pipe; if (*f_pos) @@ -226,6 +231,10 @@ if (!s->dev) return -EIO; + buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count; if (copy_from_user (buffer, buf, bytes_to_write)) { ret = -EFAULT; @@ -258,6 +267,7 @@ } out: + kfree(buffer); return ret ? ret : bytes_written; } @@ -387,7 +397,11 @@ static void tiglusb_disconnect (struct usb_interface *intf) { + wait_queue_t __wait; ptiglusb_t s = usb_get_intfdata (intf); + + init_waitqueue_entry(&__wait, current); + usb_set_intfdata (intf, NULL); if (!s || !s->dev) { @@ -397,8 +411,12 @@ s->remove_pending = 1; wake_up (&s->wait); + add_wait_queue(&s->wait, &__wait); + set_current_state(TASK_UNINTERRUPTIBLE); if (s->state == _started) - sleep_on (&s->remove_ok); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&s->wait, &__wait); down (&s->mutex); s->dev = NULL; s->opened = 0; diff -urN linux-2.6.2-rc2/drivers/usb/serial/kobil_sct.c linux-2.6.2-rc3/drivers/usb/serial/kobil_sct.c --- linux-2.6.2-rc2/drivers/usb/serial/kobil_sct.c 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/serial/kobil_sct.c 2004-01-30 18:49:23.000000000 -0800 @@ -651,7 +651,7 @@ return 0; case TCSETS: // 0x5402 - if (! &port->tty->termios) { + if (!(port->tty->termios)) { dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); return -ENOTTY; } diff -urN linux-2.6.2-rc2/drivers/usb/serial/whiteheat.c linux-2.6.2-rc3/drivers/usb/serial/whiteheat.c --- linux-2.6.2-rc2/drivers/usb/serial/whiteheat.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/serial/whiteheat.c 2004-01-30 18:49:23.000000000 -0800 @@ -353,8 +353,8 @@ int pipe; int ret; int alen; - __u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 }; - __u8 result[sizeof(*hw_info) + 1]; + __u8 *command; + __u8 *result; int i; int j; struct urb *urb; @@ -365,13 +365,22 @@ command_port = serial->port[COMMAND_PORT]; pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress); + command = kmalloc(2, GFP_KERNEL); + if (!command) + goto no_command_buffer; + command[0] = WHITEHEAT_GET_HW_INFO; + command[1] = 0; + + result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL); + if (!result) + goto no_result_buffer; /* * When the module is reloaded the firmware is still there and * the endpoints are still in the usb core unchanged. This is the * unlinking bug in disguise. Same for the call below. */ usb_clear_halt(serial->dev, pipe); - ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, COMMAND_TIMEOUT); + ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT); if (ret) { err("%s: Couldn't send command [%d]", serial->type->name, ret); goto no_firmware; @@ -383,7 +392,7 @@ pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress); /* See the comment on the usb_clear_halt() above */ usb_clear_halt(serial->dev, pipe); - ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, COMMAND_TIMEOUT); + ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT); if (ret) { err("%s: Couldn't get results [%d]", serial->type->name, ret); goto no_firmware; @@ -485,6 +494,8 @@ usb_set_serial_port_data(command_port, command_info); command_port->write_urb->complete = command_port_write_callback; command_port->read_urb->complete = command_port_read_callback; + kfree(result); + kfree(command); return 0; @@ -526,6 +537,10 @@ no_private: ; } + kfree(result); +no_result_buffer: + kfree(command); +no_command_buffer: return -ENOMEM; } diff -urN linux-2.6.2-rc2/drivers/usb/storage/scsiglue.c linux-2.6.2-rc3/drivers/usb/storage/scsiglue.c --- linux-2.6.2-rc2/drivers/usb/storage/scsiglue.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/storage/scsiglue.c 2004-01-30 18:49:23.000000000 -0800 @@ -309,44 +309,6 @@ * Sysfs interface ***********************************************************************/ -/* Output routine for the sysfs info file */ -static ssize_t show_info(struct device *dev, char *buffer) -{ - char *pos = buffer; - const int length = PAGE_SIZE; - - struct scsi_device *sdev = to_scsi_device(dev); - struct us_data *us = (struct us_data*)sdev->host->hostdata[0]; - - /* print the controller name */ - SPRINTF(" Host scsi%d: usb-storage\n", sdev->host->host_no); - - /* print product, vendor, and serial number strings */ - SPRINTF(" Vendor: %s\n", us->vendor); - SPRINTF(" Product: %s\n", us->product); - SPRINTF("Serial Number: %s\n", us->serial); - - /* show the protocol and transport */ - SPRINTF(" Protocol: %s\n", us->protocol_name); - SPRINTF(" Transport: %s\n", us->transport_name); - - /* show the device flags */ - if (pos < buffer + length) { - pos += sprintf(pos, " Quirks:"); - - DO_FLAG(SINGLE_LUN); - DO_FLAG(SCM_MULT_TARG); - DO_FLAG(FIX_INQUIRY); - DO_FLAG(FIX_CAPACITY); - - *(pos++) = '\n'; - } - - return (pos - buffer); -} - -static DEVICE_ATTR(info, S_IRUGO, show_info, NULL); - /* Output routine for the sysfs max_sectors file */ static ssize_t show_max_sectors(struct device *dev, char *buf) { @@ -373,7 +335,6 @@ store_max_sectors); static struct device_attribute *sysfs_device_attr_list[] = { - &dev_attr_info, &dev_attr_max_sectors, NULL, }; diff -urN linux-2.6.2-rc2/drivers/usb/storage/unusual_devs.h linux-2.6.2-rc3/drivers/usb/storage/unusual_devs.h --- linux-2.6.2-rc2/drivers/usb/storage/unusual_devs.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/drivers/usb/storage/unusual_devs.h 2004-01-30 18:49:23.000000000 -0800 @@ -115,6 +115,13 @@ "DVD-CAM DZ-MV100A Camcorder", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), +/* Reported by Simon Levitt + * This entry needs Sub and Proto fields */ +UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, + "Epson", + "875DC Storage", + US_SC_SCSI, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + /* Reported by Khalid Aziz * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, @@ -482,11 +489,6 @@ "Freecom", "USB-IDE", US_SC_QIC, US_PR_FREECOM, freecom_init, 0), - -UNUSUAL_DEV( 0x07ab, 0xfc84, 0x0000, 0x9999, - "Freecom", - "FX-5/FX-50", - US_SC_QIC, US_PR_FREECOM, freecom_init, 0), #endif UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, diff -urN linux-2.6.2-rc2/drivers/video/console/fbcon.c linux-2.6.2-rc3/drivers/video/console/fbcon.c --- linux-2.6.2-rc2/drivers/video/console/fbcon.c 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/drivers/video/console/fbcon.c 2004-01-30 18:49:23.000000000 -0800 @@ -545,7 +545,7 @@ return display_desc; done = 1; - info = registered_fb[num_registered_fb-1]; + info = registered_fb[0]; if (!info) return NULL; info->currcon = -1; diff -urN linux-2.6.2-rc2/fs/xfs/Makefile linux-2.6.2-rc3/fs/xfs/Makefile --- linux-2.6.2-rc2/fs/xfs/Makefile 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/Makefile 2004-01-30 18:49:23.000000000 -0800 @@ -30,7 +30,7 @@ # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ # -EXTRA_CFLAGS += -Ifs/xfs -funsigned-char +EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux -funsigned-char ifeq ($(CONFIG_XFS_DEBUG),y) EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG -DXFSDEBUG @@ -83,6 +83,7 @@ xfs_alloc_btree.o \ xfs_attr.o \ xfs_attr_leaf.o \ + xfs_behavior.o \ xfs_bit.o \ xfs_bmap.o \ xfs_bmap_btree.o \ @@ -106,6 +107,7 @@ xfs_inode.o \ xfs_inode_item.o \ xfs_iocore.o \ + xfs_iomap.o \ xfs_itable.o \ xfs_dfrag.o \ xfs_log.o \ @@ -126,18 +128,15 @@ xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o -# Objects in pagebuf/ -xfs-y += pagebuf/page_buf.o - # Objects in linux/ xfs-y += $(addprefix linux/, \ + mrlock.o \ xfs_aops.o \ - xfs_behavior.o \ + xfs_buf.o \ xfs_file.o \ xfs_fs_subr.o \ xfs_globals.o \ xfs_ioctl.o \ - xfs_iomap.o \ xfs_iops.o \ xfs_lrw.o \ xfs_super.o \ @@ -148,7 +147,6 @@ xfs-y += $(addprefix support/, \ debug.o \ move.o \ - mrlock.o \ qsort.o \ uuid.o) diff -urN linux-2.6.2-rc2/fs/xfs/linux/kmem.h linux-2.6.2-rc3/fs/xfs/linux/kmem.h --- linux-2.6.2-rc2/fs/xfs/linux/kmem.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/kmem.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_KMEM_H__ +#define __XFS_SUPPORT_KMEM_H__ + +#include +#include +#include +#include + +/* + * Cutoff point to use vmalloc instead of kmalloc. + */ +#define MAX_SLAB_SIZE 0x10000 + +/* + * XFS uses slightly different names for these due to the + * IRIX heritage. + */ +#define kmem_zone kmem_cache_s +#define kmem_zone_t kmem_cache_t + +#define KM_SLEEP 0x0001 +#define KM_NOSLEEP 0x0002 +#define KM_NOFS 0x0004 + +typedef unsigned long xfs_pflags_t; + +#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) + +#define PFLAGS_SET_FSTRANS(STATEP) do { \ + *(STATEP) = current->flags; \ + current->flags |= PF_FSTRANS; \ +} while (0) + +#define PFLAGS_RESTORE(STATEP) do { \ + current->flags = *(STATEP); \ +} while (0) + +#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \ + *(NSTATEP) = *(OSTATEP); \ +} while (0) + +/* + * XXX get rid of the unconditional __GFP_NOFAIL by adding + * a KM_FAIL flag and using it where we're allowed to fail. + */ +static __inline unsigned int +kmem_flags_convert(int flags) +{ + int lflags; + +#if DEBUG + if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) { + printk(KERN_WARNING + "XFS: memory allocation with wrong flags (%x)\n", flags); + BUG(); + } +#endif + + lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL); + + /* avoid recusive callbacks to filesystem during transactions */ + if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS)) + lflags &= ~__GFP_FS; + + return lflags; +} + +static __inline void * +kmem_alloc(size_t size, int flags) +{ + if (unlikely(MAX_SLAB_SIZE < size)) + /* Avoid doing filesystem sensitive stuff to get this */ + return __vmalloc(size, kmem_flags_convert(flags), PAGE_KERNEL); + return kmalloc(size, kmem_flags_convert(flags)); +} + +static __inline void * +kmem_zalloc(size_t size, int flags) +{ + void *ptr = kmem_alloc(size, flags); + if (likely(ptr != NULL)) + memset(ptr, 0, size); + return ptr; +} + +static __inline void +kmem_free(void *ptr, size_t size) +{ + if (unlikely((unsigned long)ptr < VMALLOC_START || + (unsigned long)ptr >= VMALLOC_END)) + kfree(ptr); + else + vfree(ptr); +} + +static __inline void * +kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags) +{ + void *new = kmem_alloc(newsize, flags); + + if (likely(ptr != NULL)) { + if (likely(new != NULL)) + memcpy(new, ptr, min(oldsize, newsize)); + kmem_free(ptr, oldsize); + } + + return new; +} + +static __inline kmem_zone_t * +kmem_zone_init(int size, char *zone_name) +{ + return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL); +} + +static __inline void * +kmem_zone_alloc(kmem_zone_t *zone, int flags) +{ + return kmem_cache_alloc(zone, kmem_flags_convert(flags)); +} + +static __inline void * +kmem_zone_zalloc(kmem_zone_t *zone, int flags) +{ + void *ptr = kmem_zone_alloc(zone, flags); + if (likely(ptr != NULL)) + memset(ptr, 0, kmem_cache_size(zone)); + return ptr; +} + +static __inline void +kmem_zone_free(kmem_zone_t *zone, void *ptr) +{ + kmem_cache_free(zone, ptr); +} + +typedef struct shrinker *kmem_shaker_t; +typedef int (*kmem_shake_func_t)(int, unsigned int); + +static __inline kmem_shaker_t +kmem_shake_register(kmem_shake_func_t sfunc) +{ + return set_shrinker(DEFAULT_SEEKS, sfunc); +} + +static __inline void +kmem_shake_deregister(kmem_shaker_t shrinker) +{ + remove_shrinker(shrinker); +} + +static __inline int +kmem_shake_allow(unsigned int gfp_mask) +{ + return (gfp_mask & __GFP_WAIT); +} + +#endif /* __XFS_SUPPORT_KMEM_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/mrlock.c linux-2.6.2-rc3/fs/xfs/linux/mrlock.c --- linux-2.6.2-rc2/fs/xfs/linux/mrlock.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/mrlock.c 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include +#include +#include +#include +#include + +#include "mrlock.h" + + +#if USE_RW_WAIT_QUEUE_SPINLOCK +# define wq_write_lock write_lock +#else +# define wq_write_lock spin_lock +#endif + +/* + * We don't seem to need lock_type (only one supported), name, or + * sequence. But, XFS will pass it so let's leave them here for now. + */ +/* ARGSUSED */ +void +mrlock_init(mrlock_t *mrp, int lock_type, char *name, long sequence) +{ + mrp->mr_count = 0; + mrp->mr_reads_waiting = 0; + mrp->mr_writes_waiting = 0; + init_waitqueue_head(&mrp->mr_readerq); + init_waitqueue_head(&mrp->mr_writerq); + mrp->mr_lock = SPIN_LOCK_UNLOCKED; +} + +/* + * Macros to lock/unlock the mrlock_t. + */ + +#define MRLOCK(m) spin_lock(&(m)->mr_lock); +#define MRUNLOCK(m) spin_unlock(&(m)->mr_lock); + + +/* + * lock_wait should never be called in an interrupt thread. + * + * mrlocks can sleep (i.e. call schedule) and so they can't ever + * be called from an interrupt thread. + * + * threads that wake-up should also never be invoked from interrupt threads. + * + * But, waitqueue_lock is locked from interrupt threads - and we are + * called with interrupts disabled, so it is all OK. + */ + +/* ARGSUSED */ +void +lock_wait(wait_queue_head_t *q, spinlock_t *lock, int rw) +{ + DECLARE_WAITQUEUE( wait, current ); + + __set_current_state(TASK_UNINTERRUPTIBLE); + + spin_lock(&q->lock); + if (rw) { + __add_wait_queue_tail(q, &wait); + } else { + __add_wait_queue(q, &wait); + } + + spin_unlock(&q->lock); + spin_unlock(lock); + + schedule(); + + spin_lock(&q->lock); + __remove_wait_queue(q, &wait); + spin_unlock(&q->lock); + + spin_lock(lock); + + /* return with lock held */ +} + +/* ARGSUSED */ +void +mrfree(mrlock_t *mrp) +{ +} + +/* ARGSUSED */ +void +mrlock(mrlock_t *mrp, int type, int flags) +{ + if (type == MR_ACCESS) + mraccess(mrp); + else + mrupdate(mrp); +} + +/* ARGSUSED */ +void +mraccessf(mrlock_t *mrp, int flags) +{ + MRLOCK(mrp); + if(mrp->mr_writes_waiting > 0) { + mrp->mr_reads_waiting++; + lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); + mrp->mr_reads_waiting--; + } + while (mrp->mr_count < 0) { + mrp->mr_reads_waiting++; + lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); + mrp->mr_reads_waiting--; + } + mrp->mr_count++; + MRUNLOCK(mrp); +} + +/* ARGSUSED */ +void +mrupdatef(mrlock_t *mrp, int flags) +{ + MRLOCK(mrp); + while(mrp->mr_count) { + mrp->mr_writes_waiting++; + lock_wait(&mrp->mr_writerq, &mrp->mr_lock, 1); + mrp->mr_writes_waiting--; + } + + mrp->mr_count = -1; /* writer on it */ + MRUNLOCK(mrp); +} + +int +mrtryaccess(mrlock_t *mrp) +{ + MRLOCK(mrp); + /* + * If anyone is waiting for update access or the lock is held for update + * fail the request. + */ + if(mrp->mr_writes_waiting > 0 || mrp->mr_count < 0) { + MRUNLOCK(mrp); + return 0; + } + mrp->mr_count++; + MRUNLOCK(mrp); + return 1; +} + +int +mrtrypromote(mrlock_t *mrp) +{ + MRLOCK(mrp); + + if(mrp->mr_count == 1) { /* We are the only thread with the lock */ + mrp->mr_count = -1; /* writer on it */ + MRUNLOCK(mrp); + return 1; + } + + MRUNLOCK(mrp); + return 0; +} + +int +mrtryupdate(mrlock_t *mrp) +{ + MRLOCK(mrp); + + if(mrp->mr_count) { + MRUNLOCK(mrp); + return 0; + } + + mrp->mr_count = -1; /* writer on it */ + MRUNLOCK(mrp); + return 1; +} + +static __inline__ void mrwake(mrlock_t *mrp) +{ + /* + * First, if the count is now 0, we need to wake-up anyone waiting. + */ + if (!mrp->mr_count) { + if (mrp->mr_writes_waiting) { /* Wake-up first writer waiting */ + wake_up(&mrp->mr_writerq); + } else if (mrp->mr_reads_waiting) { /* Wakeup any readers waiting */ + wake_up(&mrp->mr_readerq); + } + } +} + +void +mraccunlock(mrlock_t *mrp) +{ + MRLOCK(mrp); + mrp->mr_count--; + mrwake(mrp); + MRUNLOCK(mrp); +} + +void +mrunlock(mrlock_t *mrp) +{ + MRLOCK(mrp); + if (mrp->mr_count < 0) { + mrp->mr_count = 0; + } else { + mrp->mr_count--; + } + mrwake(mrp); + MRUNLOCK(mrp); +} + +int +ismrlocked(mrlock_t *mrp, int type) /* No need to lock since info can change */ +{ + if (type == MR_ACCESS) + return (mrp->mr_count > 0); /* Read lock */ + else if (type == MR_UPDATE) + return (mrp->mr_count < 0); /* Write lock */ + else if (type == (MR_UPDATE | MR_ACCESS)) + return (mrp->mr_count); /* Any type of lock held */ + else /* Any waiters */ + return (mrp->mr_reads_waiting | mrp->mr_writes_waiting); +} + +/* + * Demote from update to access. We better be the only thread with the + * lock in update mode so it should be easy to set to 1. + * Wake-up any readers waiting. + */ + +void +mrdemote(mrlock_t *mrp) +{ + MRLOCK(mrp); + mrp->mr_count = 1; + if (mrp->mr_reads_waiting) { /* Wakeup all readers waiting */ + wake_up(&mrp->mr_readerq); + } + MRUNLOCK(mrp); +} diff -urN linux-2.6.2-rc2/fs/xfs/linux/mrlock.h linux-2.6.2-rc3/fs/xfs/linux/mrlock.h --- linux-2.6.2-rc2/fs/xfs/linux/mrlock.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/mrlock.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_MRLOCK_H__ +#define __XFS_SUPPORT_MRLOCK_H__ + +#include +#include +#include +#include + +/* + * Implement mrlocks on Linux that work for XFS. + * + * These are sleep locks and not spinlocks. If one wants read/write spinlocks, + * use read_lock, write_lock, ... see spinlock.h. + */ + +typedef struct mrlock_s { + int mr_count; + unsigned short mr_reads_waiting; + unsigned short mr_writes_waiting; + wait_queue_head_t mr_readerq; + wait_queue_head_t mr_writerq; + spinlock_t mr_lock; +} mrlock_t; + +#define MR_ACCESS 1 +#define MR_UPDATE 2 + +#define MRLOCK_BARRIER 0x1 +#define MRLOCK_ALLOW_EQUAL_PRI 0x8 + +/* + * mraccessf/mrupdatef take flags to be passed in while sleeping; + * only PLTWAIT is currently supported. + */ + +extern void mraccessf(mrlock_t *, int); +extern void mrupdatef(mrlock_t *, int); +extern void mrlock(mrlock_t *, int, int); +extern void mrunlock(mrlock_t *); +extern void mraccunlock(mrlock_t *); +extern int mrtryupdate(mrlock_t *); +extern int mrtryaccess(mrlock_t *); +extern int mrtrypromote(mrlock_t *); +extern void mrdemote(mrlock_t *); + +extern int ismrlocked(mrlock_t *, int); +extern void mrlock_init(mrlock_t *, int type, char *name, long sequence); +extern void mrfree(mrlock_t *); + +#define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1) +#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */ +#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */ +#define mrislocked_access(mrp) ((mrp)->mr_count > 0) +#define mrislocked_update(mrp) ((mrp)->mr_count < 0) + +#endif /* __XFS_SUPPORT_MRLOCK_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/mutex.h linux-2.6.2-rc3/fs/xfs/linux/mutex.h --- linux-2.6.2-rc2/fs/xfs/linux/mutex.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/mutex.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_MUTEX_H__ +#define __XFS_SUPPORT_MUTEX_H__ + +#include +#include + +/* + * Map the mutex'es from IRIX to Linux semaphores. + * + * Destroy just simply initializes to -99 which should block all other + * callers. + */ +#define MUTEX_DEFAULT 0x0 +typedef struct semaphore mutex_t; + +#define mutex_init(lock, type, name) sema_init(lock, 1) +#define mutex_destroy(lock) sema_init(lock, -99) +#define mutex_lock(lock, num) down(lock) +#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) +#define mutex_unlock(lock) up(lock) + +#endif /* __XFS_SUPPORT_MUTEX_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/sema.h linux-2.6.2-rc3/fs/xfs/linux/sema.h --- linux-2.6.2-rc2/fs/xfs/linux/sema.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/sema.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_SEMA_H__ +#define __XFS_SUPPORT_SEMA_H__ + +#include +#include +#include +#include + +/* + * sema_t structure just maps to struct semaphore in Linux kernel. + */ + +typedef struct semaphore sema_t; + +#define init_sema(sp, val, c, d) sema_init(sp, val) +#define initsema(sp, val) sema_init(sp, val) +#define initnsema(sp, val, name) sema_init(sp, val) +#define psema(sp, b) down(sp) +#define vsema(sp) up(sp) +#define valusema(sp) (atomic_read(&(sp)->count)) +#define freesema(sema) + +/* + * Map cpsema (try to get the sema) to down_trylock. We need to switch + * the return values since cpsema returns 1 (acquired) 0 (failed) and + * down_trylock returns the reverse 0 (acquired) 1 (failed). + */ + +#define cpsema(sp) (down_trylock(sp) ? 0 : 1) + +/* + * Didn't do cvsema(sp). Not sure how to map this to up/down/... + * It does a vsema if the values is < 0 other wise nothing. + */ + +#endif /* __XFS_SUPPORT_SEMA_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/spin.h linux-2.6.2-rc3/fs/xfs/linux/spin.h --- linux-2.6.2-rc2/fs/xfs/linux/spin.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/spin.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_SPIN_H__ +#define __XFS_SUPPORT_SPIN_H__ + +#include /* preempt needs this */ +#include + +/* + * Map lock_t from IRIX to Linux spinlocks. + * + * Note that linux turns on/off spinlocks depending on CONFIG_SMP. + * We don't need to worry about SMP or not here. + */ + +#define SPLDECL(s) unsigned long s + +typedef spinlock_t lock_t; + +#define spinlock_init(lock, name) spin_lock_init(lock) +#define spinlock_destroy(lock) + +static inline unsigned long mutex_spinlock(lock_t *lock) +{ + spin_lock(lock); + return 0; +} + +/*ARGSUSED*/ +static inline void mutex_spinunlock(lock_t *lock, unsigned long s) +{ + spin_unlock(lock); +} + +static inline void nested_spinlock(lock_t *lock) +{ + spin_lock(lock); +} + +static inline void nested_spinunlock(lock_t *lock) +{ + spin_unlock(lock); +} + +#endif /* __XFS_SUPPORT_SPIN_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/sv.h linux-2.6.2-rc3/fs/xfs/linux/sv.h --- linux-2.6.2-rc2/fs/xfs/linux/sv.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/sv.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_SV_H__ +#define __XFS_SUPPORT_SV_H__ + +#include +#include +#include + +/* + * Synchronisation variables. + * + * (Parameters "pri", "svf" and "rts" are not implemented) + */ + +typedef struct sv_s { + wait_queue_head_t waiters; +} sv_t; + +#define SV_FIFO 0x0 /* sv_t is FIFO type */ +#define SV_LIFO 0x2 /* sv_t is LIFO type */ +#define SV_PRIO 0x4 /* sv_t is PRIO type */ +#define SV_KEYED 0x6 /* sv_t is KEYED type */ +#define SV_DEFAULT SV_FIFO + + +static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state, + unsigned long timeout) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue_exclusive(&sv->waiters, &wait); + __set_current_state(state); + spin_unlock(lock); + + schedule_timeout(timeout); + + remove_wait_queue(&sv->waiters, &wait); +} + +#define init_sv(sv,type,name,flag) \ + init_waitqueue_head(&(sv)->waiters) +#define sv_init(sv,flag,name) \ + init_waitqueue_head(&(sv)->waiters) +#define sv_destroy(sv) \ + /*NOTHING*/ +#define sv_wait(sv, pri, lock, s) \ + _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) +#define sv_wait_sig(sv, pri, lock, s) \ + _sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) +#define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \ + _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts)) +#define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \ + _sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts)) +#define sv_signal(sv) \ + wake_up(&(sv)->waiters) +#define sv_broadcast(sv) \ + wake_up_all(&(sv)->waiters) + +#endif /* __XFS_SUPPORT_SV_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/time.h linux-2.6.2-rc3/fs/xfs/linux/time.h --- linux-2.6.2-rc2/fs/xfs/linux/time.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/time.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_TIME_H__ +#define __XFS_SUPPORT_TIME_H__ + +#include +#include + +typedef struct timespec timespec_t; + +static inline void delay(long ticks) +{ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(ticks); +} + +static inline void nanotime(struct timespec *tvp) +{ + *tvp = CURRENT_TIME; +} + +#endif /* __XFS_SUPPORT_TIME_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_behavior.c linux-2.6.2-rc3/fs/xfs/linux/xfs_behavior.c --- linux-2.6.2-rc2/fs/xfs/linux/xfs_behavior.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_behavior.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - * - */ -#include "xfs.h" - -/* - * Source file used to associate/disassociate behaviors with virtualized - * objects. See xfs_behavior.h for more information about behaviors, etc. - * - * The implementation is split between functions in this file and macros - * in xfs_behavior.h. - */ - -/* - * Insert a new behavior descriptor into a behavior chain. - * - * The behavior chain is ordered based on the 'position' number which - * lives in the first field of the ops vector (higher numbers first). - * - * Attemps to insert duplicate ops result in an EINVAL return code. - * Otherwise, return 0 to indicate success. - */ -int -bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) -{ - bhv_desc_t *curdesc, *prev; - int position; - - /* - * Validate the position value of the new behavior. - */ - position = BHV_POSITION(bdp); - ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); - - /* - * Find location to insert behavior. Check for duplicates. - */ - prev = NULL; - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - /* Check for duplication. */ - if (curdesc->bd_ops == bdp->bd_ops) { - ASSERT(0); - return EINVAL; - } - - /* Find correct position */ - if (position >= BHV_POSITION(curdesc)) { - ASSERT(position != BHV_POSITION(curdesc)); - break; /* found it */ - } - - prev = curdesc; - } - - if (prev == NULL) { - /* insert at front of chain */ - bdp->bd_next = bhp->bh_first; - bhp->bh_first = bdp; - } else { - /* insert after prev */ - bdp->bd_next = prev->bd_next; - prev->bd_next = bdp; - } - - return 0; -} - -/* - * Remove a behavior descriptor from a position in a behavior chain; - * the postition is guaranteed not to be the first position. - * Should only be called by the bhv_remove() macro. - */ -void -bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) -{ - bhv_desc_t *curdesc, *prev; - - ASSERT(bhp->bh_first != NULL); - ASSERT(bhp->bh_first->bd_next != NULL); - - prev = bhp->bh_first; - for (curdesc = bhp->bh_first->bd_next; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc == bdp) - break; /* found it */ - prev = curdesc; - } - - ASSERT(curdesc == bdp); - prev->bd_next = bdp->bd_next; /* remove from after prev */ -} - -/* - * Look for a specific ops vector on the specified behavior chain. - * Return the associated behavior descriptor. Or NULL, if not found. - */ -bhv_desc_t * -bhv_lookup(bhv_head_t *bhp, void *ops) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc->bd_ops == ops) - return curdesc; - } - - return NULL; -} - -/* - * Looks for the first behavior within a specified range of positions. - * Return the associated behavior descriptor. Or NULL, if none found. - */ -bhv_desc_t * -bhv_lookup_range(bhv_head_t *bhp, int low, int high) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - int position = BHV_POSITION(curdesc); - - if (position <= high) { - if (position >= low) - return curdesc; - return NULL; - } - } - - return NULL; -} - -/* - * Return the base behavior in the chain, or NULL if the chain - * is empty. - * - * The caller has not read locked the behavior chain, so acquire the - * lock before traversing the chain. - */ -bhv_desc_t * -bhv_base(bhv_head_t *bhp) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc->bd_next == NULL) { - return curdesc; - } - } - - return NULL; -} - -void -bhv_head_init( - bhv_head_t *bhp, - char *name) -{ - bhp->bh_first = NULL; -} - -void -bhv_insert_initial( - bhv_head_t *bhp, - bhv_desc_t *bdp) -{ - ASSERT(bhp->bh_first == NULL); - (bhp)->bh_first = bdp; -} - -void -bhv_head_destroy( - bhv_head_t *bhp) -{ - ASSERT(bhp->bh_first == NULL); -} diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_behavior.h linux-2.6.2-rc3/fs/xfs/linux/xfs_behavior.h --- linux-2.6.2-rc2/fs/xfs/linux/xfs_behavior.h 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_behavior.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_BEHAVIOR_H__ -#define __XFS_BEHAVIOR_H__ - -/* - * Header file used to associate behaviors with virtualized objects. - * - * A virtualized object is an internal, virtualized representation of - * OS entities such as persistent files, processes, or sockets. Examples - * of virtualized objects include vnodes, vprocs, and vsockets. Often - * a virtualized object is referred to simply as an "object." - * - * A behavior is essentially an implementation layer associated with - * an object. Multiple behaviors for an object are chained together, - * the order of chaining determining the order of invocation. Each - * behavior of a given object implements the same set of interfaces - * (e.g., the VOP interfaces). - * - * Behaviors may be dynamically inserted into an object's behavior chain, - * such that the addition is transparent to consumers that already have - * references to the object. Typically, a given behavior will be inserted - * at a particular location in the behavior chain. Insertion of new - * behaviors is synchronized with operations-in-progress (oip's) so that - * the oip's always see a consistent view of the chain. - * - * The term "interpostion" is used to refer to the act of inserting - * a behavior such that it interposes on (i.e., is inserted in front - * of) a particular other behavior. A key example of this is when a - * system implementing distributed single system image wishes to - * interpose a distribution layer (providing distributed coherency) - * in front of an object that is otherwise only accessed locally. - * - * Note that the traditional vnode/inode combination is simply a virtualized - * object that has exactly one associated behavior. - * - * Behavior synchronization is logic which is necessary under certain - * circumstances that there is no conflict between ongoing operations - * traversing the behavior chain and those dunamically modifying the - * behavior chain. Because behavior synchronization adds extra overhead - * to virtual operation invocation, we want to restrict, as much as - * we can, the requirement for this extra code, to those situations - * in which it is truly necessary. - * - * Behavior synchronization is needed whenever there's at least one class - * of object in the system for which: - * 1) multiple behaviors for a given object are supported, - * -- AND -- - * 2a) insertion of a new behavior can happen dynamically at any time during - * the life of an active object, - * -- AND -- - * 3a) insertion of a new behavior needs to synchronize with existing - * ops-in-progress. - * -- OR -- - * 3b) multiple different behaviors can be dynamically inserted at - * any time during the life of an active object - * -- OR -- - * 3c) removal of a behavior can occur at any time during the life of - * an active object. - * -- OR -- - * 2b) removal of a behavior can occur at any time during the life of an - * active object - * - */ - -struct bhv_head_lock; - -/* - * Behavior head. Head of the chain of behaviors. - * Contained within each virtualized object data structure. - */ -typedef struct bhv_head { - struct bhv_desc *bh_first; /* first behavior in chain */ - struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */ -} bhv_head_t; - -/* - * Behavior descriptor. Descriptor associated with each behavior. - * Contained within the behavior's private data structure. - */ -typedef struct bhv_desc { - void *bd_pdata; /* private data for this behavior */ - void *bd_vobj; /* virtual object associated with */ - void *bd_ops; /* ops for this behavior */ - struct bhv_desc *bd_next; /* next behavior in chain */ -} bhv_desc_t; - -/* - * Behavior identity field. A behavior's identity determines the position - * where it lives within a behavior chain, and it's always the first field - * of the behavior's ops vector. The optional id field further identifies the - * subsystem responsible for the behavior. - */ -typedef struct bhv_identity { - __u16 bi_id; /* owning subsystem id */ - __u16 bi_position; /* position in chain */ -} bhv_identity_t; - -typedef bhv_identity_t bhv_position_t; - -#define BHV_IDENTITY_INIT(id,pos) {id, pos} -#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos) - -/* - * Define boundaries of position values. - */ -#define BHV_POSITION_INVALID 0 /* invalid position number */ -#define BHV_POSITION_BASE 1 /* base (last) implementation layer */ -#define BHV_POSITION_TOP 63 /* top (first) implementation layer */ - -/* - * Plumbing macros. - */ -#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first) -#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next) -#define BHV_NEXTNULL(bdp) ((bdp)->bd_next) -#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj) -#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj) -#define BHV_PDATA(bdp) (bdp)->bd_pdata -#define BHV_OPS(bdp) (bdp)->bd_ops -#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops) -#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position) - -extern void bhv_head_init(bhv_head_t *, char *); -extern void bhv_head_destroy(bhv_head_t *); -extern int bhv_insert(bhv_head_t *, bhv_desc_t *); -extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); - -/* - * Initialize a new behavior descriptor. - * Arguments: - * bdp - pointer to behavior descriptor - * pdata - pointer to behavior's private data - * vobj - pointer to associated virtual object - * ops - pointer to ops for this behavior - */ -#define bhv_desc_init(bdp, pdata, vobj, ops) \ - { \ - (bdp)->bd_pdata = pdata; \ - (bdp)->bd_vobj = vobj; \ - (bdp)->bd_ops = ops; \ - (bdp)->bd_next = NULL; \ - } - -/* - * Remove a behavior descriptor from a behavior chain. - */ -#define bhv_remove(bhp, bdp) \ - { \ - if ((bhp)->bh_first == (bdp)) { \ - /* \ - * Remove from front of chain. \ - * Atomic wrt oip's. \ - */ \ - (bhp)->bh_first = (bdp)->bd_next; \ - } else { \ - /* remove from non-front of chain */ \ - bhv_remove_not_first(bhp, bdp); \ - } \ - (bdp)->bd_vobj = NULL; \ - } - -/* - * Behavior module prototypes. - */ -extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp); -extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops); -extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high); -extern bhv_desc_t * bhv_base(bhv_head_t *bhp); - -/* No bhv locking on Linux */ -#define bhv_lookup_unlocked bhv_lookup -#define bhv_base_unlocked bhv_base - -#endif /* __XFS_BEHAVIOR_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_buf.c linux-2.6.2-rc3/fs/xfs/linux/xfs_buf.c --- linux-2.6.2-rc2/fs/xfs/linux/xfs_buf.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_buf.c 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,2058 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +/* + * page_buf.c + * + * The page_buf module provides an abstract buffer cache model on top of + * the Linux page cache. Cached metadata blocks for a file system are + * hashed to the inode for the block device. The page_buf module + * assembles buffer (page_buf_t) objects on demand to aggregate such + * cached pages for I/O. + * + * + * Written by Steve Lord, Jim Mostek, Russell Cattelan + * and Rajagopal Ananthanarayanan ("ananth") at SGI. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "kmem.h" + +#include "xfs_types.h" +#include "xfs_cred.h" +#include "xfs_lrw.h" +#include "xfs_buf.h" + +#define BBSHIFT 9 +#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1) + +#ifndef GFP_READAHEAD +#define GFP_READAHEAD (__GFP_NOWARN|__GFP_NORETRY) +#endif + +/* + * File wide globals + */ + +STATIC kmem_cache_t *pagebuf_cache; +STATIC void pagebuf_daemon_wakeup(void); +STATIC void pagebuf_delwri_queue(page_buf_t *, int); +STATIC struct workqueue_struct *pagebuf_logio_workqueue; +STATIC struct workqueue_struct *pagebuf_dataio_workqueue; + +/* + * Pagebuf module configuration parameters, exported via + * /proc/sys/vm/pagebuf + */ + +typedef struct pb_sysctl_val { + int min; + int val; + int max; +} pb_sysctl_val_t; + +struct { + pb_sysctl_val_t flush_interval; /* interval between runs of the + * delwri flush daemon. */ + pb_sysctl_val_t age_buffer; /* time for buffer to age before + * we flush it. */ + pb_sysctl_val_t stats_clear; /* clear the pagebuf stats */ + pb_sysctl_val_t debug; /* debug tracing on or off */ +} pb_params = { + /* MIN DFLT MAX */ + .flush_interval = { HZ/2, HZ, 30*HZ }, + .age_buffer = { 1*HZ, 15*HZ, 300*HZ }, + .stats_clear = { 0, 0, 1 }, + .debug = { 0, 0, 1 }, +}; + +enum { + PB_FLUSH_INT = 1, + PB_FLUSH_AGE = 2, + PB_STATS_CLEAR = 3, + PB_DEBUG = 4, +}; + +/* + * Pagebuf statistics variables + */ + +struct pbstats { + u_int32_t pb_get; + u_int32_t pb_create; + u_int32_t pb_get_locked; + u_int32_t pb_get_locked_waited; + u_int32_t pb_busy_locked; + u_int32_t pb_miss_locked; + u_int32_t pb_page_retries; + u_int32_t pb_page_found; + u_int32_t pb_get_read; +} pbstats; +DEFINE_PER_CPU(struct pbstats, pbstats); + +/* We don't disable preempt, not too worried about poking the + * wrong cpu's stat for now */ +#define PB_STATS_INC(count) (__get_cpu_var(pbstats).count++) + +/* + * Pagebuf debugging + */ + +#ifdef PAGEBUF_TRACE +void +pagebuf_trace( + page_buf_t *pb, + char *id, + void *data, + void *ra) +{ + if (!pb_params.debug.val) + return; + ktrace_enter(pagebuf_trace_buf, + pb, id, + (void *)(unsigned long)pb->pb_flags, + (void *)(unsigned long)pb->pb_hold.counter, + (void *)(unsigned long)pb->pb_sema.count.counter, + (void *)current, + data, ra, + (void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff), + (void *)(unsigned long)(pb->pb_file_offset & 0xffffffff), + (void *)(unsigned long)pb->pb_buffer_length, + NULL, NULL, NULL, NULL, NULL); +} +ktrace_t *pagebuf_trace_buf; +#define PAGEBUF_TRACE_SIZE 4096 +#define PB_TRACE(pb, id, data) \ + pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0)) +#else +#define PB_TRACE(pb, id, data) do { } while (0) +#endif + +#ifdef PAGEBUF_LOCK_TRACKING +# define PB_SET_OWNER(pb) ((pb)->pb_last_holder = current->pid) +# define PB_CLEAR_OWNER(pb) ((pb)->pb_last_holder = -1) +# define PB_GET_OWNER(pb) ((pb)->pb_last_holder) +#else +# define PB_SET_OWNER(pb) do { } while (0) +# define PB_CLEAR_OWNER(pb) do { } while (0) +# define PB_GET_OWNER(pb) do { } while (0) +#endif + +/* + * Pagebuf allocation / freeing. + */ + +#define pb_to_gfp(flags) \ + (((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \ + ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) + +#define pb_to_km(flags) \ + (((flags) & PBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP) + + +#define pagebuf_allocate(flags) \ + kmem_zone_alloc(pagebuf_cache, pb_to_km(flags)) +#define pagebuf_deallocate(pb) \ + kmem_zone_free(pagebuf_cache, (pb)); + +/* + * Pagebuf hashing + */ + +#define NBITS 8 +#define NHASH (1<pb_hash_index] + +STATIC int +_bhash( + struct block_device *bdev, + loff_t base) +{ + int bit, hval; + + base >>= 9; + base ^= (unsigned long)bdev / L1_CACHE_BYTES; + for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) { + hval ^= (int)base & (NHASH-1); + base >>= NBITS; + } + return hval; +} + +/* + * Mapping of multi-page buffers into contiguous virtual space + */ + +STATIC void *pagebuf_mapout_locked(page_buf_t *); + +typedef struct a_list { + void *vm_addr; + struct a_list *next; +} a_list_t; + +STATIC a_list_t *as_free_head; +STATIC int as_list_len; +STATIC spinlock_t as_lock = SPIN_LOCK_UNLOCKED; + +/* + * Try to batch vunmaps because they are costly. + */ +STATIC void +free_address( + void *addr) +{ + a_list_t *aentry; + + aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC); + if (aentry) { + spin_lock(&as_lock); + aentry->next = as_free_head; + aentry->vm_addr = addr; + as_free_head = aentry; + as_list_len++; + spin_unlock(&as_lock); + } else { + vunmap(addr); + } +} + +STATIC void +purge_addresses(void) +{ + a_list_t *aentry, *old; + + if (as_free_head == NULL) + return; + + spin_lock(&as_lock); + aentry = as_free_head; + as_free_head = NULL; + as_list_len = 0; + spin_unlock(&as_lock); + + while ((old = aentry) != NULL) { + vunmap(aentry->vm_addr); + aentry = aentry->next; + kfree(old); + } +} + +/* + * Internal pagebuf object manipulation + */ + +STATIC void +_pagebuf_initialize( + page_buf_t *pb, + pb_target_t *target, + loff_t range_base, + size_t range_length, + page_buf_flags_t flags) +{ + /* + * We don't want certain flags to appear in pb->pb_flags. + */ + flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD); + + memset(pb, 0, sizeof(page_buf_t)); + atomic_set(&pb->pb_hold, 1); + init_MUTEX_LOCKED(&pb->pb_iodonesema); + INIT_LIST_HEAD(&pb->pb_list); + INIT_LIST_HEAD(&pb->pb_hash_list); + init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */ + PB_SET_OWNER(pb); + pb->pb_target = target; + pb->pb_file_offset = range_base; + /* + * Set buffer_length and count_desired to the same value initially. + * IO routines should use count_desired, which will be the same in + * most cases but may be reset (e.g. XFS recovery). + */ + pb->pb_buffer_length = pb->pb_count_desired = range_length; + pb->pb_flags = flags | PBF_NONE; + pb->pb_bn = PAGE_BUF_DADDR_NULL; + atomic_set(&pb->pb_pin_count, 0); + init_waitqueue_head(&pb->pb_waiters); + + PB_STATS_INC(pb_create); + PB_TRACE(pb, "initialize", target); +} + +/* + * Allocate a page array capable of holding a specified number + * of pages, and point the page buf at it. + */ +STATIC int +_pagebuf_get_pages( + page_buf_t *pb, + int page_count, + page_buf_flags_t flags) +{ + int gpf_mask = pb_to_gfp(flags); + + /* Make sure that we have a page list */ + if (pb->pb_pages == NULL) { + pb->pb_offset = page_buf_poff(pb->pb_file_offset); + pb->pb_page_count = page_count; + if (page_count <= PB_PAGES) { + pb->pb_pages = pb->pb_page_array; + } else { + pb->pb_pages = kmalloc(sizeof(struct page *) * + page_count, gpf_mask); + if (pb->pb_pages == NULL) + return -ENOMEM; + } + memset(pb->pb_pages, 0, sizeof(struct page *) * page_count); + } + return 0; +} + +/* + * Walk a pagebuf releasing all the pages contained within it. + */ +STATIC inline void +_pagebuf_freepages( + page_buf_t *pb) +{ + int buf_index; + + for (buf_index = 0; buf_index < pb->pb_page_count; buf_index++) { + struct page *page = pb->pb_pages[buf_index]; + + if (page) { + pb->pb_pages[buf_index] = NULL; + page_cache_release(page); + } + } +} + +/* + * pagebuf_free + * + * pagebuf_free releases the specified buffer. The modification + * state of any associated pages is left unchanged. + */ +void +pagebuf_free( + page_buf_t *pb) +{ + PB_TRACE(pb, "free", 0); + + if (pb->pb_flags & _PBF_LOCKABLE) { + pb_hash_t *hash = pb_hash(pb); + + spin_lock(&hash->pb_hash_lock); + /* + * Someone grabbed a reference while we weren't looking, + * try again later. + */ + if (unlikely(atomic_read(&pb->pb_hold))) { + spin_unlock(&hash->pb_hash_lock); + return; + } else if (!list_empty(&pb->pb_hash_list)) + list_del_init(&pb->pb_hash_list); + spin_unlock(&hash->pb_hash_lock); + } + + /* release any virtual mapping */ ; + if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { + void *vaddr = pagebuf_mapout_locked(pb); + if (vaddr) { + free_address(vaddr); + } + } + + if (pb->pb_flags & _PBF_MEM_ALLOCATED) { + if (pb->pb_pages) { + /* release the pages in the address list */ + if ((pb->pb_pages[0]) && + (pb->pb_flags & _PBF_MEM_SLAB)) { + kfree(pb->pb_addr); + } else { + _pagebuf_freepages(pb); + } + if (pb->pb_pages != pb->pb_page_array) + kfree(pb->pb_pages); + pb->pb_pages = NULL; + } + pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); + } + + pagebuf_deallocate(pb); +} + +/* + * _pagebuf_lookup_pages + * + * _pagebuf_lookup_pages finds all pages which match the buffer + * in question and the range of file offsets supplied, + * and builds the page list for the buffer, if the + * page list is not already formed or if not all of the pages are + * already in the list. Invalid pages (pages which have not yet been + * read in from disk) are assigned for any pages which are not found. + */ +STATIC int +_pagebuf_lookup_pages( + page_buf_t *pb, + struct address_space *aspace, + page_buf_flags_t flags) +{ + loff_t next_buffer_offset; + unsigned long page_count, pi, index; + struct page *page; + int gfp_mask, retry_count = 5, rval = 0; + int all_mapped, good_pages, nbytes; + unsigned int blocksize, sectorshift; + size_t size, offset; + + + /* For pagebufs where we want to map an address, do not use + * highmem pages - so that we do not need to use kmap resources + * to access the data. + * + * For pages where the caller has indicated there may be resource + * contention (e.g. called from a transaction) do not flush + * delalloc pages to obtain memory. + */ + + if (flags & PBF_READ_AHEAD) { + gfp_mask = GFP_READAHEAD; + retry_count = 0; + } else if (flags & PBF_DONT_BLOCK) { + gfp_mask = GFP_NOFS; + } else if (flags & PBF_MAPPABLE) { + gfp_mask = GFP_KERNEL; + } else { + gfp_mask = GFP_HIGHUSER; + } + + next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length; + + good_pages = page_count = (page_buf_btoc(next_buffer_offset) - + page_buf_btoct(pb->pb_file_offset)); + + if (pb->pb_flags & _PBF_ALL_PAGES_MAPPED) { + /* Bring pages forward in cache */ + for (pi = 0; pi < page_count; pi++) { + mark_page_accessed(pb->pb_pages[pi]); + } + if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) { + all_mapped = 1; + goto mapit; + } + return 0; + } + + /* Ensure pb_pages field has been initialised */ + rval = _pagebuf_get_pages(pb, page_count, flags); + if (rval) + return rval; + + rval = pi = 0; + blocksize = pb->pb_target->pbr_bsize; + sectorshift = pb->pb_target->pbr_sshift; + size = pb->pb_count_desired; + offset = pb->pb_offset; + + /* Enter the pages in the page list */ + index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT; + for (all_mapped = 1; pi < page_count; pi++, index++) { + if (pb->pb_pages[pi] == 0) { + retry: + page = find_or_create_page(aspace, index, gfp_mask); + if (!page) { + if (--retry_count > 0) { + PB_STATS_INC(pb_page_retries); + pagebuf_daemon_wakeup(); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(10); + goto retry; + } + rval = -ENOMEM; + all_mapped = 0; + continue; + } + PB_STATS_INC(pb_page_found); + mark_page_accessed(page); + pb->pb_pages[pi] = page; + } else { + page = pb->pb_pages[pi]; + lock_page(page); + } + + nbytes = PAGE_CACHE_SIZE - offset; + if (nbytes > size) + nbytes = size; + size -= nbytes; + + if (!PageUptodate(page)) { + if (blocksize == PAGE_CACHE_SIZE) { + if (flags & PBF_READ) + pb->pb_locked = 1; + good_pages--; + } else if (!PagePrivate(page)) { + unsigned long i, range; + + /* + * In this case page->private holds a bitmap + * of uptodate sectors within the page + */ + ASSERT(blocksize < PAGE_CACHE_SIZE); + range = (offset + nbytes) >> sectorshift; + for (i = offset >> sectorshift; i < range; i++) + if (!test_bit(i, &page->private)) + break; + if (i != range) + good_pages--; + } else { + good_pages--; + } + } + offset = 0; + } + + if (!pb->pb_locked) { + for (pi = 0; pi < page_count; pi++) { + if (pb->pb_pages[pi]) + unlock_page(pb->pb_pages[pi]); + } + } + +mapit: + pb->pb_flags |= _PBF_MEM_ALLOCATED; + if (all_mapped) { + pb->pb_flags |= _PBF_ALL_PAGES_MAPPED; + + /* A single page buffer is always mappable */ + if (page_count == 1) { + pb->pb_addr = (caddr_t) + page_address(pb->pb_pages[0]) + pb->pb_offset; + pb->pb_flags |= PBF_MAPPED; + } else if (flags & PBF_MAPPED) { + if (as_list_len > 64) + purge_addresses(); + pb->pb_addr = vmap(pb->pb_pages, page_count, + VM_MAP, PAGE_KERNEL); + if (pb->pb_addr == NULL) + return -ENOMEM; + pb->pb_addr += pb->pb_offset; + pb->pb_flags |= PBF_MAPPED | _PBF_ADDR_ALLOCATED; + } + } + /* If some pages were found with data in them + * we are not in PBF_NONE state. + */ + if (good_pages != 0) { + pb->pb_flags &= ~(PBF_NONE); + if (good_pages != page_count) { + pb->pb_flags |= PBF_PARTIAL; + } + } + + PB_TRACE(pb, "lookup_pages", (long)good_pages); + + return rval; +} + +/* + * Finding and Reading Buffers + */ + +/* + * _pagebuf_find + * + * Looks up, and creates if absent, a lockable buffer for + * a given range of an inode. The buffer is returned + * locked. If other overlapping buffers exist, they are + * released before the new buffer is created and locked, + * which may imply that this call will block until those buffers + * are unlocked. No I/O is implied by this call. + */ +STATIC page_buf_t * +_pagebuf_find( /* find buffer for block */ + pb_target_t *target,/* target for block */ + loff_t ioff, /* starting offset of range */ + size_t isize, /* length of range */ + page_buf_flags_t flags, /* PBF_TRYLOCK */ + page_buf_t *new_pb)/* newly allocated buffer */ +{ + loff_t range_base; + size_t range_length; + int hval; + pb_hash_t *h; + struct list_head *p; + page_buf_t *pb; + int not_locked; + + range_base = (ioff << BBSHIFT); + range_length = (isize << BBSHIFT); + + /* Ensure we never do IOs smaller than the sector size */ + BUG_ON(range_length < (1 << target->pbr_sshift)); + + /* Ensure we never do IOs that are not sector aligned */ + BUG_ON(range_base & (loff_t)target->pbr_smask); + + hval = _bhash(target->pbr_bdev, range_base); + h = &pbhash[hval]; + + spin_lock(&h->pb_hash_lock); + list_for_each(p, &h->pb_hash) { + pb = list_entry(p, page_buf_t, pb_hash_list); + + if (pb->pb_target == target && + pb->pb_file_offset == range_base && + pb->pb_buffer_length == range_length && + atomic_read(&pb->pb_hold)) { + /* If we look at something bring it to the + * front of the list for next time + */ + atomic_inc(&pb->pb_hold); + list_move(&pb->pb_hash_list, &h->pb_hash); + goto found; + } + } + + /* No match found */ + if (new_pb) { + _pagebuf_initialize(new_pb, target, range_base, + range_length, flags | _PBF_LOCKABLE); + new_pb->pb_hash_index = hval; + list_add(&new_pb->pb_hash_list, &h->pb_hash); + } else { + PB_STATS_INC(pb_miss_locked); + } + + spin_unlock(&h->pb_hash_lock); + return (new_pb); + +found: + spin_unlock(&h->pb_hash_lock); + + /* Attempt to get the semaphore without sleeping, + * if this does not work then we need to drop the + * spinlock and do a hard attempt on the semaphore. + */ + not_locked = down_trylock(&pb->pb_sema); + if (not_locked) { + if (!(flags & PBF_TRYLOCK)) { + /* wait for buffer ownership */ + PB_TRACE(pb, "get_lock", 0); + pagebuf_lock(pb); + PB_STATS_INC(pb_get_locked_waited); + } else { + /* We asked for a trylock and failed, no need + * to look at file offset and length here, we + * know that this pagebuf at least overlaps our + * pagebuf and is locked, therefore our buffer + * either does not exist, or is this buffer + */ + + pagebuf_rele(pb); + PB_STATS_INC(pb_busy_locked); + return (NULL); + } + } else { + /* trylock worked */ + PB_SET_OWNER(pb); + } + + if (pb->pb_flags & PBF_STALE) + pb->pb_flags &= PBF_MAPPABLE | \ + PBF_MAPPED | \ + _PBF_LOCKABLE | \ + _PBF_ALL_PAGES_MAPPED | \ + _PBF_ADDR_ALLOCATED | \ + _PBF_MEM_ALLOCATED | \ + _PBF_MEM_SLAB; + PB_TRACE(pb, "got_lock", 0); + PB_STATS_INC(pb_get_locked); + return (pb); +} + + +/* + * pagebuf_find + * + * pagebuf_find returns a buffer matching the specified range of + * data for the specified target, if any of the relevant blocks + * are in memory. The buffer may have unallocated holes, if + * some, but not all, of the blocks are in memory. Even where + * pages are present in the buffer, not all of every page may be + * valid. + */ +page_buf_t * +pagebuf_find( /* find buffer for block */ + /* if the block is in memory */ + pb_target_t *target,/* target for block */ + loff_t ioff, /* starting offset of range */ + size_t isize, /* length of range */ + page_buf_flags_t flags) /* PBF_TRYLOCK */ +{ + return _pagebuf_find(target, ioff, isize, flags, NULL); +} + +/* + * pagebuf_get + * + * pagebuf_get assembles a buffer covering the specified range. + * Some or all of the blocks in the range may be valid. Storage + * in memory for all portions of the buffer will be allocated, + * although backing storage may not be. If PBF_READ is set in + * flags, pagebuf_iostart is called also. + */ +page_buf_t * +pagebuf_get( /* allocate a buffer */ + pb_target_t *target,/* target for buffer */ + loff_t ioff, /* starting offset of range */ + size_t isize, /* length of range */ + page_buf_flags_t flags) /* PBF_TRYLOCK */ +{ + page_buf_t *pb, *new_pb; + int error; + + new_pb = pagebuf_allocate(flags); + if (unlikely(!new_pb)) + return (NULL); + + pb = _pagebuf_find(target, ioff, isize, flags, new_pb); + if (pb != new_pb) { + pagebuf_deallocate(new_pb); + if (unlikely(!pb)) + return (NULL); + } + + PB_STATS_INC(pb_get); + + /* fill in any missing pages */ + error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags); + if (unlikely(error)) { + pagebuf_free(pb); + return (NULL); + } + + /* + * Always fill in the block number now, the mapped cases can do + * their own overlay of this later. + */ + pb->pb_bn = ioff; + pb->pb_count_desired = pb->pb_buffer_length; + + if (flags & PBF_READ) { + if (PBF_NOT_DONE(pb)) { + PB_TRACE(pb, "get_read", (unsigned long)flags); + PB_STATS_INC(pb_get_read); + pagebuf_iostart(pb, flags); + } else if (flags & PBF_ASYNC) { + PB_TRACE(pb, "get_read_async", (unsigned long)flags); + /* + * Read ahead call which is already satisfied, + * drop the buffer + */ + if (flags & (PBF_LOCK | PBF_TRYLOCK)) + pagebuf_unlock(pb); + pagebuf_rele(pb); + return NULL; + } else { + PB_TRACE(pb, "get_read_done", (unsigned long)flags); + /* We do not want read in the flags */ + pb->pb_flags &= ~PBF_READ; + } + } else { + PB_TRACE(pb, "get_write", (unsigned long)flags); + } + return (pb); +} + +/* + * Create a skeletal pagebuf (no pages associated with it). + */ +page_buf_t * +pagebuf_lookup( + struct pb_target *target, + loff_t ioff, + size_t isize, + page_buf_flags_t flags) +{ + page_buf_t *pb; + + pb = pagebuf_allocate(flags); + if (pb) { + _pagebuf_initialize(pb, target, ioff, isize, flags); + } + return pb; +} + +/* + * If we are not low on memory then do the readahead in a deadlock + * safe manner. + */ +void +pagebuf_readahead( + pb_target_t *target, + loff_t ioff, + size_t isize, + page_buf_flags_t flags) +{ + struct backing_dev_info *bdi; + + bdi = target->pbr_mapping->backing_dev_info; + if (bdi_read_congested(bdi)) + return; + if (bdi_write_congested(bdi)) + return; + + flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD); + pagebuf_get(target, ioff, isize, flags); +} + +page_buf_t * +pagebuf_get_empty( + size_t len, + pb_target_t *target) +{ + page_buf_t *pb; + + pb = pagebuf_allocate(_PBF_LOCKABLE); + if (pb) + _pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE); + return pb; +} + +static inline struct page * +mem_to_page( + void *addr) +{ + if (((unsigned long)addr < VMALLOC_START) || + ((unsigned long)addr >= VMALLOC_END)) { + return virt_to_page(addr); + } else { + return vmalloc_to_page(addr); + } +} + +int +pagebuf_associate_memory( + page_buf_t *pb, + void *mem, + size_t len) +{ + int rval; + int i = 0; + size_t ptr; + size_t end, end_cur; + off_t offset; + int page_count; + + page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; + offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK); + if (offset && (len > PAGE_CACHE_SIZE)) + page_count++; + + /* Free any previous set of page pointers */ + if (pb->pb_pages && (pb->pb_pages != pb->pb_page_array)) { + kfree(pb->pb_pages); + } + pb->pb_pages = NULL; + pb->pb_addr = mem; + + rval = _pagebuf_get_pages(pb, page_count, 0); + if (rval) + return rval; + + pb->pb_offset = offset; + ptr = (size_t) mem & PAGE_CACHE_MASK; + end = PAGE_CACHE_ALIGN((size_t) mem + len); + end_cur = end; + /* set up first page */ + pb->pb_pages[0] = mem_to_page(mem); + + ptr += PAGE_CACHE_SIZE; + pb->pb_page_count = ++i; + while (ptr < end) { + pb->pb_pages[i] = mem_to_page((void *)ptr); + pb->pb_page_count = ++i; + ptr += PAGE_CACHE_SIZE; + } + pb->pb_locked = 0; + + pb->pb_count_desired = pb->pb_buffer_length = len; + pb->pb_flags |= PBF_MAPPED; + + return 0; +} + +page_buf_t * +pagebuf_get_no_daddr( + size_t len, + pb_target_t *target) +{ + int rval; + void *rmem = NULL; + page_buf_flags_t flags = _PBF_LOCKABLE | PBF_FORCEIO; + page_buf_t *pb; + size_t tlen = 0; + + if (unlikely(len > 0x20000)) + return NULL; + + pb = pagebuf_allocate(flags); + if (!pb) + return NULL; + + _pagebuf_initialize(pb, target, 0, len, flags); + + do { + if (tlen == 0) { + tlen = len; /* first time */ + } else { + kfree(rmem); /* free the mem from the previous try */ + tlen <<= 1; /* double the size and try again */ + } + if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) { + pagebuf_free(pb); + return NULL; + } + } while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask)); + + if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) { + kfree(rmem); + pagebuf_free(pb); + return NULL; + } + /* otherwise pagebuf_free just ignores it */ + pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB); + PB_CLEAR_OWNER(pb); + up(&pb->pb_sema); /* Return unlocked pagebuf */ + + PB_TRACE(pb, "no_daddr", rmem); + + return pb; +} + + +/* + * pagebuf_hold + * + * Increment reference count on buffer, to hold the buffer concurrently + * with another thread which may release (free) the buffer asynchronously. + * + * Must hold the buffer already to call this function. + */ +void +pagebuf_hold( + page_buf_t *pb) +{ + atomic_inc(&pb->pb_hold); + PB_TRACE(pb, "hold", 0); +} + +/* + * pagebuf_rele + * + * pagebuf_rele releases a hold on the specified buffer. If the + * the hold count is 1, pagebuf_rele calls pagebuf_free. + */ +void +pagebuf_rele( + page_buf_t *pb) +{ + PB_TRACE(pb, "rele", pb->pb_relse); + + if (atomic_dec_and_test(&pb->pb_hold)) { + int do_free = 1; + + if (pb->pb_relse) { + atomic_inc(&pb->pb_hold); + (*(pb->pb_relse)) (pb); + do_free = 0; + } + if (pb->pb_flags & PBF_DELWRI) { + pb->pb_flags |= PBF_ASYNC; + atomic_inc(&pb->pb_hold); + pagebuf_delwri_queue(pb, 0); + do_free = 0; + } else if (pb->pb_flags & PBF_FS_MANAGED) { + do_free = 0; + } + + if (do_free) { + pagebuf_free(pb); + } + } +} + + +/* + * Mutual exclusion on buffers. Locking model: + * + * Buffers associated with inodes for which buffer locking + * is not enabled are not protected by semaphores, and are + * assumed to be exclusively owned by the caller. There is a + * spinlock in the buffer, used by the caller when concurrent + * access is possible. + */ + +/* + * pagebuf_cond_lock + * + * pagebuf_cond_lock locks a buffer object, if it is not already locked. + * Note that this in no way + * locks the underlying pages, so it is only useful for synchronizing + * concurrent use of page buffer objects, not for synchronizing independent + * access to the underlying pages. + */ +int +pagebuf_cond_lock( /* lock buffer, if not locked */ + /* returns -EBUSY if locked) */ + page_buf_t *pb) +{ + int locked; + + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + locked = down_trylock(&pb->pb_sema) == 0; + if (locked) { + PB_SET_OWNER(pb); + } + PB_TRACE(pb, "cond_lock", (long)locked); + return(locked ? 0 : -EBUSY); +} + +/* + * pagebuf_lock_value + * + * Return lock value for a pagebuf + */ +int +pagebuf_lock_value( + page_buf_t *pb) +{ + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + return(atomic_read(&pb->pb_sema.count)); +} + +/* + * pagebuf_lock + * + * pagebuf_lock locks a buffer object. Note that this in no way + * locks the underlying pages, so it is only useful for synchronizing + * concurrent use of page buffer objects, not for synchronizing independent + * access to the underlying pages. + */ +int +pagebuf_lock( + page_buf_t *pb) +{ + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + + PB_TRACE(pb, "lock", 0); + if (atomic_read(&pb->pb_io_remaining)) + blk_run_queues(); + down(&pb->pb_sema); + PB_SET_OWNER(pb); + PB_TRACE(pb, "locked", 0); + return 0; +} + +/* + * pagebuf_unlock + * + * pagebuf_unlock releases the lock on the buffer object created by + * pagebuf_lock or pagebuf_cond_lock (not any + * pinning of underlying pages created by pagebuf_pin). + */ +void +pagebuf_unlock( /* unlock buffer */ + page_buf_t *pb) /* buffer to unlock */ +{ + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + PB_CLEAR_OWNER(pb); + up(&pb->pb_sema); + PB_TRACE(pb, "unlock", 0); +} + + +/* + * Pinning Buffer Storage in Memory + */ + +/* + * pagebuf_pin + * + * pagebuf_pin locks all of the memory represented by a buffer in + * memory. Multiple calls to pagebuf_pin and pagebuf_unpin, for + * the same or different buffers affecting a given page, will + * properly count the number of outstanding "pin" requests. The + * buffer may be released after the pagebuf_pin and a different + * buffer used when calling pagebuf_unpin, if desired. + * pagebuf_pin should be used by the file system when it wants be + * assured that no attempt will be made to force the affected + * memory to disk. It does not assure that a given logical page + * will not be moved to a different physical page. + */ +void +pagebuf_pin( + page_buf_t *pb) +{ + atomic_inc(&pb->pb_pin_count); + PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter); +} + +/* + * pagebuf_unpin + * + * pagebuf_unpin reverses the locking of memory performed by + * pagebuf_pin. Note that both functions affected the logical + * pages associated with the buffer, not the buffer itself. + */ +void +pagebuf_unpin( + page_buf_t *pb) +{ + if (atomic_dec_and_test(&pb->pb_pin_count)) { + wake_up_all(&pb->pb_waiters); + } + PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter); +} + +int +pagebuf_ispin( + page_buf_t *pb) +{ + return atomic_read(&pb->pb_pin_count); +} + +/* + * pagebuf_wait_unpin + * + * pagebuf_wait_unpin waits until all of the memory associated + * with the buffer is not longer locked in memory. It returns + * immediately if none of the affected pages are locked. + */ +static inline void +_pagebuf_wait_unpin( + page_buf_t *pb) +{ + DECLARE_WAITQUEUE (wait, current); + + if (atomic_read(&pb->pb_pin_count) == 0) + return; + + add_wait_queue(&pb->pb_waiters, &wait); + for (;;) { + current->state = TASK_UNINTERRUPTIBLE; + if (atomic_read(&pb->pb_pin_count) == 0) + break; + if (atomic_read(&pb->pb_io_remaining)) + blk_run_queues(); + schedule(); + } + remove_wait_queue(&pb->pb_waiters, &wait); + current->state = TASK_RUNNING; +} + +/* + * Buffer Utility Routines + */ + +/* + * pagebuf_iodone + * + * pagebuf_iodone marks a buffer for which I/O is in progress + * done with respect to that I/O. The pb_iodone routine, if + * present, will be called as a side-effect. + */ +void +pagebuf_iodone_work( + void *v) +{ + page_buf_t *pb = (page_buf_t *)v; + + if (pb->pb_iodone) { + (*(pb->pb_iodone)) (pb); + return; + } + + if (pb->pb_flags & PBF_ASYNC) { + if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse) + pagebuf_unlock(pb); + pagebuf_rele(pb); + } +} + +void +pagebuf_iodone( + page_buf_t *pb, + int dataio, + int schedule) +{ + pb->pb_flags &= ~(PBF_READ | PBF_WRITE); + if (pb->pb_error == 0) { + pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE); + } + + PB_TRACE(pb, "iodone", pb->pb_iodone); + + if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { + if (schedule) { + INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); + queue_work(dataio ? pagebuf_dataio_workqueue : + pagebuf_logio_workqueue, &pb->pb_iodone_work); + } else { + pagebuf_iodone_work(pb); + } + } else { + up(&pb->pb_iodonesema); + } +} + +/* + * pagebuf_ioerror + * + * pagebuf_ioerror sets the error code for a buffer. + */ +void +pagebuf_ioerror( /* mark/clear buffer error flag */ + page_buf_t *pb, /* buffer to mark */ + unsigned int error) /* error to store (0 if none) */ +{ + pb->pb_error = error; + PB_TRACE(pb, "ioerror", (unsigned long)error); +} + +/* + * pagebuf_iostart + * + * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied. + * If necessary, it will arrange for any disk space allocation required, + * and it will break up the request if the block mappings require it. + * The pb_iodone routine in the buffer supplied will only be called + * when all of the subsidiary I/O requests, if any, have been completed. + * pagebuf_iostart calls the pagebuf_ioinitiate routine or + * pagebuf_iorequest, if the former routine is not defined, to start + * the I/O on a given low-level request. + */ +int +pagebuf_iostart( /* start I/O on a buffer */ + page_buf_t *pb, /* buffer to start */ + page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */ + /* PBF_WRITE, PBF_DELWRI, */ + /* PBF_SYNC, PBF_DONT_BLOCK */ +{ + int status = 0; + + PB_TRACE(pb, "iostart", (unsigned long)flags); + + if (flags & PBF_DELWRI) { + pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC); + pb->pb_flags |= flags & + (PBF_DELWRI | PBF_ASYNC | PBF_SYNC); + pagebuf_delwri_queue(pb, 1); + return status; + } + + pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \ + PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES); + pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \ + PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES); + + BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL); + + /* For writes allow an alternate strategy routine to precede + * the actual I/O request (which may not be issued at all in + * a shutdown situation, for example). + */ + status = (flags & PBF_WRITE) ? + pagebuf_iostrategy(pb) : pagebuf_iorequest(pb); + + /* Wait for I/O if we are not an async request. + * Note: async I/O request completion will release the buffer, + * and that can already be done by this point. So using the + * buffer pointer from here on, after async I/O, is invalid. + */ + if (!status && !(flags & PBF_ASYNC)) + status = pagebuf_iowait(pb); + + return status; +} + +/* + * Helper routine for pagebuf_iorequest + */ + +STATIC __inline__ int +_pagebuf_iolocked( + page_buf_t *pb) +{ + ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE)); + if (pb->pb_flags & PBF_READ) + return pb->pb_locked; + return ((pb->pb_flags & _PBF_LOCKABLE) == 0); +} + +STATIC __inline__ void +_pagebuf_iodone( + page_buf_t *pb, + int schedule) +{ + if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { + pb->pb_locked = 0; + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), schedule); + } +} + +STATIC int +bio_end_io_pagebuf( + struct bio *bio, + unsigned int bytes_done, + int error) +{ + page_buf_t *pb = (page_buf_t *)bio->bi_private; + unsigned int i, blocksize = pb->pb_target->pbr_bsize; + unsigned int sectorshift = pb->pb_target->pbr_sshift; + struct bio_vec *bvec = bio->bi_io_vec; + + if (bio->bi_size) + return 1; + + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + pb->pb_error = EIO; + + for (i = 0; i < bio->bi_vcnt; i++, bvec++) { + struct page *page = bvec->bv_page; + + if (pb->pb_error) { + SetPageError(page); + } else if (blocksize == PAGE_CACHE_SIZE) { + SetPageUptodate(page); + } else if (!PagePrivate(page)) { + unsigned int j, range; + + ASSERT(blocksize < PAGE_CACHE_SIZE); + range = (bvec->bv_offset + bvec->bv_len) >> sectorshift; + for (j = bvec->bv_offset >> sectorshift; j < range; j++) + set_bit(j, &page->private); + if (page->private == (unsigned long)(PAGE_CACHE_SIZE-1)) + SetPageUptodate(page); + } + + if (_pagebuf_iolocked(pb)) { + unlock_page(page); + } + } + + _pagebuf_iodone(pb, 1); + bio_put(bio); + return 0; +} + +void +_pagebuf_ioapply( + page_buf_t *pb) +{ + int i, map_i, total_nr_pages, nr_pages; + struct bio *bio; + int offset = pb->pb_offset; + int size = pb->pb_count_desired; + sector_t sector = pb->pb_bn; + unsigned int blocksize = pb->pb_target->pbr_bsize; + int locking = _pagebuf_iolocked(pb); + + total_nr_pages = pb->pb_page_count; + map_i = 0; + + /* Special code path for reading a sub page size pagebuf in -- + * we populate up the whole page, and hence the other metadata + * in the same page. This optimization is only valid when the + * filesystem block size and the page size are equal. + */ + if ((pb->pb_buffer_length < PAGE_CACHE_SIZE) && + (pb->pb_flags & PBF_READ) && locking && + (blocksize == PAGE_CACHE_SIZE)) { + bio = bio_alloc(GFP_NOIO, 1); + + bio->bi_bdev = pb->pb_target->pbr_bdev; + bio->bi_sector = sector - (offset >> BBSHIFT); + bio->bi_end_io = bio_end_io_pagebuf; + bio->bi_private = pb; + + bio_add_page(bio, pb->pb_pages[0], PAGE_CACHE_SIZE, 0); + size = 0; + + atomic_inc(&pb->pb_io_remaining); + + goto submit_io; + } + + /* Lock down the pages which we need to for the request */ + if (locking && (pb->pb_flags & PBF_WRITE) && (pb->pb_locked == 0)) { + for (i = 0; size; i++) { + int nbytes = PAGE_CACHE_SIZE - offset; + struct page *page = pb->pb_pages[i]; + + if (nbytes > size) + nbytes = size; + + lock_page(page); + + size -= nbytes; + offset = 0; + } + offset = pb->pb_offset; + size = pb->pb_count_desired; + } + +next_chunk: + atomic_inc(&pb->pb_io_remaining); + nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); + if (nr_pages > total_nr_pages) + nr_pages = total_nr_pages; + + bio = bio_alloc(GFP_NOIO, nr_pages); + bio->bi_bdev = pb->pb_target->pbr_bdev; + bio->bi_sector = sector; + bio->bi_end_io = bio_end_io_pagebuf; + bio->bi_private = pb; + + for (; size && nr_pages; nr_pages--, map_i++) { + int nbytes = PAGE_CACHE_SIZE - offset; + + if (nbytes > size) + nbytes = size; + + if (bio_add_page(bio, pb->pb_pages[map_i], + nbytes, offset) < nbytes) + break; + + offset = 0; + sector += nbytes >> BBSHIFT; + size -= nbytes; + total_nr_pages--; + } + +submit_io: + if (likely(bio->bi_size)) { + submit_bio((pb->pb_flags & PBF_READ) ? READ : WRITE, bio); + if (size) + goto next_chunk; + } else { + bio_put(bio); + pagebuf_ioerror(pb, EIO); + } + + if (pb->pb_flags & PBF_RUN_QUEUES) { + pb->pb_flags &= ~PBF_RUN_QUEUES; + if (atomic_read(&pb->pb_io_remaining) > 1) + blk_run_queues(); + } +} + +/* + * pagebuf_iorequest + * + * pagebuf_iorequest is the core I/O request routine. + * It assumes that the buffer is well-formed and + * mapped and ready for physical I/O, unlike + * pagebuf_iostart() and pagebuf_iophysio(). Those + * routines call the pagebuf_ioinitiate routine to start I/O, + * if it is present, or else call pagebuf_iorequest() + * directly if the pagebuf_ioinitiate routine is not present. + * + * This function will be responsible for ensuring access to the + * pages is restricted whilst I/O is in progress - for locking + * pagebufs the pagebuf lock is the mediator, for non-locking + * pagebufs the pages will be locked. In the locking case we + * need to use the pagebuf lock as multiple meta-data buffers + * will reference the same page. + */ +int +pagebuf_iorequest( /* start real I/O */ + page_buf_t *pb) /* buffer to convey to device */ +{ + PB_TRACE(pb, "iorequest", 0); + + if (pb->pb_flags & PBF_DELWRI) { + pagebuf_delwri_queue(pb, 1); + return 0; + } + + if (pb->pb_flags & PBF_WRITE) { + _pagebuf_wait_unpin(pb); + } + + pagebuf_hold(pb); + + /* Set the count to 1 initially, this will stop an I/O + * completion callout which happens before we have started + * all the I/O from calling pagebuf_iodone too early. + */ + atomic_set(&pb->pb_io_remaining, 1); + _pagebuf_ioapply(pb); + _pagebuf_iodone(pb, 0); + + pagebuf_rele(pb); + return 0; +} + +/* + * pagebuf_iowait + * + * pagebuf_iowait waits for I/O to complete on the buffer supplied. + * It returns immediately if no I/O is pending. In any case, it returns + * the error code, if any, or 0 if there is no error. + */ +int +pagebuf_iowait( + page_buf_t *pb) +{ + PB_TRACE(pb, "iowait", 0); + if (atomic_read(&pb->pb_io_remaining)) + blk_run_queues(); + down(&pb->pb_iodonesema); + PB_TRACE(pb, "iowaited", (long)pb->pb_error); + return pb->pb_error; +} + +STATIC void * +pagebuf_mapout_locked( + page_buf_t *pb) +{ + void *old_addr = NULL; + + if (pb->pb_flags & PBF_MAPPED) { + if (pb->pb_flags & _PBF_ADDR_ALLOCATED) + old_addr = pb->pb_addr - pb->pb_offset; + pb->pb_addr = NULL; + pb->pb_flags &= ~(PBF_MAPPED | _PBF_ADDR_ALLOCATED); + } + + return old_addr; /* Caller must free the address space, + * we are under a spin lock, probably + * not safe to do vfree here + */ +} + +caddr_t +pagebuf_offset( + page_buf_t *pb, + size_t offset) +{ + struct page *page; + + offset += pb->pb_offset; + + page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT]; + return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1)); +} + +/* + * pagebuf_iomove + * + * Move data into or out of a buffer. + */ +void +pagebuf_iomove( + page_buf_t *pb, /* buffer to process */ + size_t boff, /* starting buffer offset */ + size_t bsize, /* length to copy */ + caddr_t data, /* data address */ + page_buf_rw_t mode) /* read/write flag */ +{ + size_t bend, cpoff, csize; + struct page *page; + + bend = boff + bsize; + while (boff < bend) { + page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)]; + cpoff = page_buf_poff(boff + pb->pb_offset); + csize = min_t(size_t, + PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff); + + ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); + + switch (mode) { + case PBRW_ZERO: + memset(page_address(page) + cpoff, 0, csize); + break; + case PBRW_READ: + memcpy(data, page_address(page) + cpoff, csize); + break; + case PBRW_WRITE: + memcpy(page_address(page) + cpoff, data, csize); + } + + boff += csize; + data += csize; + } +} + + +/* + * Pagebuf delayed write buffer handling + */ + +STATIC LIST_HEAD(pbd_delwrite_queue); +STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED; + +STATIC void +pagebuf_delwri_queue( + page_buf_t *pb, + int unlock) +{ + PB_TRACE(pb, "delwri_q", (long)unlock); + spin_lock(&pbd_delwrite_lock); + /* If already in the queue, dequeue and place at tail */ + if (!list_empty(&pb->pb_list)) { + if (unlock) { + atomic_dec(&pb->pb_hold); + } + list_del(&pb->pb_list); + } + + list_add_tail(&pb->pb_list, &pbd_delwrite_queue); + pb->pb_flushtime = jiffies + pb_params.age_buffer.val; + spin_unlock(&pbd_delwrite_lock); + + if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) { + pagebuf_unlock(pb); + } +} + +void +pagebuf_delwri_dequeue( + page_buf_t *pb) +{ + PB_TRACE(pb, "delwri_uq", 0); + spin_lock(&pbd_delwrite_lock); + list_del_init(&pb->pb_list); + pb->pb_flags &= ~PBF_DELWRI; + spin_unlock(&pbd_delwrite_lock); +} + +STATIC void +pagebuf_runall_queues( + struct workqueue_struct *queue) +{ + flush_workqueue(queue); +} + +/* Defines for pagebuf daemon */ +STATIC DECLARE_COMPLETION(pagebuf_daemon_done); +STATIC struct task_struct *pagebuf_daemon_task; +STATIC int pagebuf_daemon_active; +STATIC int force_flush; + +STATIC void +pagebuf_daemon_wakeup(void) +{ + force_flush = 1; + barrier(); + wake_up_process(pagebuf_daemon_task); +} + +STATIC int +pagebuf_daemon( + void *data) +{ + int count; + page_buf_t *pb; + struct list_head *curr, *next, tmp; + + /* Set up the thread */ + daemonize("pagebufd"); + current->flags |= PF_MEMALLOC; + + pagebuf_daemon_task = current; + pagebuf_daemon_active = 1; + barrier(); + + INIT_LIST_HEAD(&tmp); + do { + /* swsusp */ + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(pb_params.flush_interval.val); + + spin_lock(&pbd_delwrite_lock); + + count = 0; + list_for_each_safe(curr, next, &pbd_delwrite_queue) { + pb = list_entry(curr, page_buf_t, pb_list); + + PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb)); + + if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) && + (((pb->pb_flags & _PBF_LOCKABLE) == 0) || + !pagebuf_cond_lock(pb))) { + + if (!force_flush && + time_before(jiffies, pb->pb_flushtime)) { + pagebuf_unlock(pb); + break; + } + + pb->pb_flags &= ~PBF_DELWRI; + pb->pb_flags |= PBF_WRITE; + + list_del(&pb->pb_list); + list_add(&pb->pb_list, &tmp); + + count++; + } + } + + spin_unlock(&pbd_delwrite_lock); + while (!list_empty(&tmp)) { + pb = list_entry(tmp.next, page_buf_t, pb_list); + list_del_init(&pb->pb_list); + + pagebuf_iostrategy(pb); + } + + if (as_list_len > 0) + purge_addresses(); + if (count) + blk_run_queues(); + + force_flush = 0; + } while (pagebuf_daemon_active); + + complete_and_exit(&pagebuf_daemon_done, 0); +} + +void +pagebuf_delwri_flush( + pb_target_t *target, + u_long flags, + int *pinptr) +{ + page_buf_t *pb; + struct list_head *curr, *next, tmp; + int pincount = 0; + int flush_cnt = 0; + + pagebuf_runall_queues(pagebuf_dataio_workqueue); + pagebuf_runall_queues(pagebuf_logio_workqueue); + + spin_lock(&pbd_delwrite_lock); + INIT_LIST_HEAD(&tmp); + + list_for_each_safe(curr, next, &pbd_delwrite_queue) { + pb = list_entry(curr, page_buf_t, pb_list); + + /* + * Skip other targets, markers and in progress buffers + */ + + if ((pb->pb_flags == 0) || (pb->pb_target != target) || + !(pb->pb_flags & PBF_DELWRI)) { + continue; + } + + PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb)); + if (pagebuf_ispin(pb)) { + pincount++; + continue; + } + + pb->pb_flags &= ~PBF_DELWRI; + pb->pb_flags |= PBF_WRITE; + list_move(&pb->pb_list, &tmp); + } + /* ok found all the items that can be worked on + * drop the lock and process the private list */ + spin_unlock(&pbd_delwrite_lock); + + list_for_each_safe(curr, next, &tmp) { + pb = list_entry(curr, page_buf_t, pb_list); + + if (flags & PBDF_WAIT) + pb->pb_flags &= ~PBF_ASYNC; + else + list_del_init(curr); + + pagebuf_lock(pb); + pagebuf_iostrategy(pb); + if (++flush_cnt > 32) { + blk_run_queues(); + flush_cnt = 0; + } + } + + blk_run_queues(); + + while (!list_empty(&tmp)) { + pb = list_entry(tmp.next, page_buf_t, pb_list); + + list_del_init(&pb->pb_list); + pagebuf_iowait(pb); + if (!pb->pb_relse) + pagebuf_unlock(pb); + pagebuf_rele(pb); + } + + if (pinptr) + *pinptr = pincount; +} + +STATIC int +pagebuf_daemon_start(void) +{ + int rval; + + pagebuf_logio_workqueue = create_workqueue("xfslogd"); + if (!pagebuf_logio_workqueue) + return -ENOMEM; + + pagebuf_dataio_workqueue = create_workqueue("xfsdatad"); + if (!pagebuf_dataio_workqueue) { + destroy_workqueue(pagebuf_logio_workqueue); + return -ENOMEM; + } + + rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); + if (rval < 0) { + destroy_workqueue(pagebuf_logio_workqueue); + destroy_workqueue(pagebuf_dataio_workqueue); + } + + return rval; +} + +/* + * pagebuf_daemon_stop + * + * Note: do not mark as __exit, it is called from pagebuf_terminate. + */ +STATIC void +pagebuf_daemon_stop(void) +{ + pagebuf_daemon_active = 0; + barrier(); + wait_for_completion(&pagebuf_daemon_done); + + destroy_workqueue(pagebuf_logio_workqueue); + destroy_workqueue(pagebuf_dataio_workqueue); +} + + +/* + * Pagebuf sysctl interface + */ + +STATIC int +pb_stats_clear_handler( + ctl_table *ctl, + int write, + struct file *filp, + void *buffer, + size_t *lenp) +{ + int c, ret; + int *valp = ctl->data; + + ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp); + + if (!ret && write && *valp) { + printk("XFS Clearing pbstats\n"); + for (c = 0; c < NR_CPUS; c++) { + if (!cpu_possible(c)) continue; + memset(&per_cpu(pbstats, c), 0, + sizeof(struct pbstats)); + } + pb_params.stats_clear.val = 0; + } + + return ret; +} + +STATIC struct ctl_table_header *pagebuf_table_header; + +STATIC ctl_table pagebuf_table[] = { + {PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &pb_params.flush_interval.min, &pb_params.flush_interval.max}, + + {PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &pb_params.age_buffer.min, &pb_params.age_buffer.max}, + + {PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val, + sizeof(int), 0644, NULL, &pb_stats_clear_handler, + &sysctl_intvec, NULL, + &pb_params.stats_clear.min, &pb_params.stats_clear.max}, + +#ifdef PAGEBUF_TRACE + {PB_DEBUG, "debug", &pb_params.debug.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &pb_params.debug.min, &pb_params.debug.max}, +#endif + {0} +}; + +STATIC ctl_table pagebuf_dir_table[] = { + {VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table}, + {0} +}; + +STATIC ctl_table pagebuf_root_table[] = { + {CTL_VM, "vm", NULL, 0, 0555, pagebuf_dir_table}, + {0} +}; + +#ifdef CONFIG_PROC_FS +STATIC int +pagebuf_readstats( + char *buffer, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + int c, i, len, val; + + len = 0; + len += sprintf(buffer + len, "pagebuf"); + for (i = 0; i < sizeof(struct pbstats) / sizeof(u_int32_t); i++) { + val = 0; + for (c = 0 ; c < NR_CPUS; c++) { + if (!cpu_possible(c)) continue; + val += *(((u_int32_t*)&per_cpu(pbstats, c) + i)); + } + len += sprintf(buffer + len, " %u", val); + } + buffer[len++] = '\n'; + + if (offset >= len) { + *start = buffer; + *eof = 1; + return 0; + } + *start = buffer + offset; + if ((len -= offset) > count) + return count; + *eof = 1; + + return len; +} +#endif /* CONFIG_PROC_FS */ + +/* + * Initialization and Termination + */ + +int __init +pagebuf_init(void) +{ + int i; + + pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1); + +#ifdef CONFIG_PROC_FS + if (proc_mkdir("fs/pagebuf", 0)) + create_proc_read_entry( + "fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL); +#endif + + pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (pagebuf_cache == NULL) { + printk("pagebuf: couldn't init pagebuf cache\n"); + pagebuf_terminate(); + return -ENOMEM; + } + + for (i = 0; i < NHASH; i++) { + spin_lock_init(&pbhash[i].pb_hash_lock); + INIT_LIST_HEAD(&pbhash[i].pb_hash); + } + +#ifdef PAGEBUF_TRACE + pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP); +#endif + + pagebuf_daemon_start(); + return 0; +} + + +/* + * pagebuf_terminate. + * + * Note: do not mark as __exit, this is also called from the __init code. + */ +void +pagebuf_terminate(void) +{ + pagebuf_daemon_stop(); + +#ifdef PAGEBUF_TRACE + ktrace_free(pagebuf_trace_buf); +#endif + + kmem_cache_destroy(pagebuf_cache); + + unregister_sysctl_table(pagebuf_table_header); +#ifdef CONFIG_PROC_FS + remove_proc_entry("fs/pagebuf/stat", NULL); + remove_proc_entry("fs/pagebuf", NULL); +#endif +} diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_buf.h linux-2.6.2-rc3/fs/xfs/linux/xfs_buf.h --- linux-2.6.2-rc2/fs/xfs/linux/xfs_buf.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_buf.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +/* + * Written by Steve Lord, Jim Mostek, Russell Cattelan at SGI + */ + +#ifndef __XFS_BUF_H__ +#define __XFS_BUF_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Base types + */ + +/* daddr must be signed since -1 is used for bmaps that are not yet allocated */ +typedef loff_t page_buf_daddr_t; + +#define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL)) + +#define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) +#define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) +#define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) +#define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) + +typedef enum page_buf_rw_e { + PBRW_READ = 1, /* transfer into target memory */ + PBRW_WRITE = 2, /* transfer from target memory */ + PBRW_ZERO = 3 /* Zero target memory */ +} page_buf_rw_t; + + +typedef enum page_buf_flags_e { /* pb_flags values */ + PBF_READ = (1 << 0), /* buffer intended for reading from device */ + PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ + PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */ + PBF_PARTIAL = (1 << 3), /* buffer partially read */ + PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ + PBF_NONE = (1 << 5), /* buffer not read at all */ + PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ + PBF_SYNC = (1 << 8), /* force updates to disk */ + PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ + PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ + PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */ + PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */ + + /* flags used only as arguments to access routines */ + PBF_LOCK = (1 << 13), /* lock requested */ + PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait */ + PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread */ + + /* flags used only internally */ + _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ + _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ + _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ + _PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated */ + _PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated */ + + PBF_FORCEIO = (1 << 22), /* ignore any cache state */ + PBF_FLUSH = (1 << 23), /* flush disk write cache */ + PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead */ + PBF_RUN_QUEUES = (1 << 25), /* run block device task queue */ + +} page_buf_flags_t; + +#define PBF_UPDATE (PBF_READ | PBF_WRITE) +#define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0) +#define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0) + +typedef struct pb_target { + dev_t pbr_dev; + struct block_device *pbr_bdev; + struct address_space *pbr_mapping; + unsigned int pbr_bsize; + unsigned int pbr_sshift; + size_t pbr_smask; +} pb_target_t; + +/* + * page_buf_t: Buffer structure for page cache-based buffers + * + * This buffer structure is used by the page cache buffer management routines + * to refer to an assembly of pages forming a logical buffer. The actual + * I/O is performed with buffer_head or bio structures, as required by drivers, + * for drivers which do not understand this structure. The buffer structure is + * used on temporary basis only, and discarded when released. + * + * The real data storage is recorded in the page cache. Metadata is + * hashed to the inode for the block device on which the file system resides. + * File data is hashed to the inode for the file. Pages which are only + * partially filled with data have bits set in their block_map entry + * to indicate which disk blocks in the page are not valid. + */ + +struct page_buf_s; +typedef void (*page_buf_iodone_t)(struct page_buf_s *); + /* call-back function on I/O completion */ +typedef void (*page_buf_relse_t)(struct page_buf_s *); + /* call-back function on I/O completion */ +typedef int (*page_buf_bdstrat_t)(struct page_buf_s *); + +#define PB_PAGES 4 + +typedef struct page_buf_s { + struct semaphore pb_sema; /* semaphore for lockables */ + unsigned long pb_flushtime; /* time to flush pagebuf */ + atomic_t pb_pin_count; /* pin count */ + wait_queue_head_t pb_waiters; /* unpin waiters */ + struct list_head pb_list; + page_buf_flags_t pb_flags; /* status flags */ + struct list_head pb_hash_list; + struct pb_target *pb_target; /* logical object */ + atomic_t pb_hold; /* reference count */ + page_buf_daddr_t pb_bn; /* block number for I/O */ + loff_t pb_file_offset; /* offset in file */ + size_t pb_buffer_length; /* size of buffer in bytes */ + size_t pb_count_desired; /* desired transfer size */ + void *pb_addr; /* virtual address of buffer */ + struct work_struct pb_iodone_work; + atomic_t pb_io_remaining;/* #outstanding I/O requests */ + page_buf_iodone_t pb_iodone; /* I/O completion function */ + page_buf_relse_t pb_relse; /* releasing function */ + page_buf_bdstrat_t pb_strat; /* pre-write function */ + struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */ + void *pb_fspriv; + void *pb_fspriv2; + void *pb_fspriv3; + unsigned short pb_error; /* error code on I/O */ + unsigned short pb_page_count; /* size of page array */ + unsigned short pb_offset; /* page offset in first page */ + unsigned char pb_locked; /* page array is locked */ + unsigned char pb_hash_index; /* hash table index */ + struct page **pb_pages; /* array of page pointers */ + struct page *pb_page_array[PB_PAGES]; /* inline pages */ +#ifdef PAGEBUF_LOCK_TRACKING + int pb_last_holder; +#endif +} page_buf_t; + + +/* Finding and Reading Buffers */ + +extern page_buf_t *pagebuf_find( /* find buffer for block if */ + /* the block is in memory */ + struct pb_target *, /* inode for block */ + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_LOCK */ + +extern page_buf_t *pagebuf_get( /* allocate a buffer */ + struct pb_target *, /* inode for buffer */ + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ + /* PBF_ASYNC */ + +extern page_buf_t *pagebuf_lookup( + struct pb_target *, + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_READ, PBF_WRITE, */ + /* PBF_FORCEIO, _PBF_LOCKABLE */ + +extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ + /* no memory or disk address */ + size_t len, + struct pb_target *); /* mount point "fake" inode */ + +extern page_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */ + /* without disk address */ + size_t len, + struct pb_target *); /* mount point "fake" inode */ + +extern int pagebuf_associate_memory( + page_buf_t *, + void *, + size_t); + +extern void pagebuf_hold( /* increment reference count */ + page_buf_t *); /* buffer to hold */ + +extern void pagebuf_readahead( /* read ahead into cache */ + struct pb_target *, /* target for buffer (or NULL) */ + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* additional read flags */ + +/* Releasing Buffers */ + +extern void pagebuf_free( /* deallocate a buffer */ + page_buf_t *); /* buffer to deallocate */ + +extern void pagebuf_rele( /* release hold on a buffer */ + page_buf_t *); /* buffer to release */ + +/* Locking and Unlocking Buffers */ + +extern int pagebuf_cond_lock( /* lock buffer, if not locked */ + /* (returns -EBUSY if locked) */ + page_buf_t *); /* buffer to lock */ + +extern int pagebuf_lock_value( /* return count on lock */ + page_buf_t *); /* buffer to check */ + +extern int pagebuf_lock( /* lock buffer */ + page_buf_t *); /* buffer to lock */ + +extern void pagebuf_unlock( /* unlock buffer */ + page_buf_t *); /* buffer to unlock */ + +/* Buffer Read and Write Routines */ + +extern void pagebuf_iodone( /* mark buffer I/O complete */ + page_buf_t *, /* buffer to mark */ + int, /* use data/log helper thread. */ + int); /* run completion locally, or in + * a helper thread. */ + +extern void pagebuf_ioerror( /* mark buffer in error (or not) */ + page_buf_t *, /* buffer to mark */ + unsigned int); /* error to store (0 if none) */ + +extern int pagebuf_iostart( /* start I/O on a buffer */ + page_buf_t *, /* buffer to start */ + page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ + /* PBF_READ, PBF_WRITE, */ + /* PBF_DELWRI, PBF_SYNC */ + +extern int pagebuf_iorequest( /* start real I/O */ + page_buf_t *); /* buffer to convey to device */ + +extern int pagebuf_iowait( /* wait for buffer I/O done */ + page_buf_t *); /* buffer to wait on */ + +extern void pagebuf_iomove( /* move data in/out of pagebuf */ + page_buf_t *, /* buffer to manipulate */ + size_t, /* starting buffer offset */ + size_t, /* length in buffer */ + caddr_t, /* data pointer */ + page_buf_rw_t); /* direction */ + +static inline int pagebuf_iostrategy(page_buf_t *pb) +{ + return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb); +} + +static inline int pagebuf_geterror(page_buf_t *pb) +{ + return pb ? pb->pb_error : ENOMEM; +} + +/* Buffer Utility Routines */ + +extern caddr_t pagebuf_offset( /* pointer at offset in buffer */ + page_buf_t *, /* buffer to offset into */ + size_t); /* offset */ + +/* Pinning Buffer Storage in Memory */ + +extern void pagebuf_pin( /* pin buffer in memory */ + page_buf_t *); /* buffer to pin */ + +extern void pagebuf_unpin( /* unpin buffered data */ + page_buf_t *); /* buffer to unpin */ + +extern int pagebuf_ispin( /* check if buffer is pinned */ + page_buf_t *); /* buffer to check */ + +/* Delayed Write Buffer Routines */ + +#define PBDF_WAIT 0x01 +extern void pagebuf_delwri_flush( + pb_target_t *, + unsigned long, + int *); + +extern void pagebuf_delwri_dequeue( + page_buf_t *); + +/* Buffer Daemon Setup Routines */ + +extern int pagebuf_init(void); +extern void pagebuf_terminate(void); + + +#ifdef PAGEBUF_TRACE +extern ktrace_t *pagebuf_trace_buf; +extern void pagebuf_trace( + page_buf_t *, /* buffer being traced */ + char *, /* description of operation */ + void *, /* arbitrary diagnostic value */ + void *); /* return address */ +#else +# define pagebuf_trace(pb, id, ptr, ra) do { } while (0) +#endif + +#define pagebuf_target_name(target) \ + ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; }) + + + + + +/* These are just for xfs_syncsub... it sets an internal variable + * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t + */ +#define XFS_B_ASYNC PBF_ASYNC +#define XFS_B_DELWRI PBF_DELWRI +#define XFS_B_READ PBF_READ +#define XFS_B_WRITE PBF_WRITE +#define XFS_B_STALE PBF_STALE + +#define XFS_BUF_TRYLOCK PBF_TRYLOCK +#define XFS_INCORE_TRYLOCK PBF_TRYLOCK +#define XFS_BUF_LOCK PBF_LOCK +#define XFS_BUF_MAPPED PBF_MAPPED + +#define BUF_BUSY PBF_DONT_BLOCK + +#define XFS_BUF_BFLAGS(x) ((x)->pb_flags) +#define XFS_BUF_ZEROFLAGS(x) \ + ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI)) + +#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) +#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) +#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE) +#define XFS_BUF_SUPER_STALE(x) do { \ + XFS_BUF_STALE(x); \ + xfs_buf_undelay(x); \ + XFS_BUF_DONE(x); \ + } while (0) + +#define XFS_BUF_MANAGE PBF_FS_MANAGED +#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED) + +static inline void xfs_buf_undelay(page_buf_t *pb) +{ + if (pb->pb_flags & PBF_DELWRI) { + if (pb->pb_list.next != &pb->pb_list) { + pagebuf_delwri_dequeue(pb); + pagebuf_rele(pb); + } else { + pb->pb_flags &= ~PBF_DELWRI; + } + } +} + +#define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI) +#define XFS_BUF_UNDELAYWRITE(x) xfs_buf_undelay(x) +#define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI) + +#define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no) +#define XFS_BUF_GETERROR(x) pagebuf_geterror(x) +#define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0) + +#define XFS_BUF_DONE(x) ((x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE)) +#define XFS_BUF_UNDONE(x) ((x)->pb_flags |= PBF_PARTIAL|PBF_NONE) +#define XFS_BUF_ISDONE(x) (!(PBF_NOT_DONE(x))) + +#define XFS_BUF_BUSY(x) ((x)->pb_flags |= PBF_FORCEIO) +#define XFS_BUF_UNBUSY(x) ((x)->pb_flags &= ~PBF_FORCEIO) +#define XFS_BUF_ISBUSY(x) (1) + +#define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC) +#define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) +#define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) + +#define XFS_BUF_FLUSH(x) ((x)->pb_flags |= PBF_FLUSH) +#define XFS_BUF_UNFLUSH(x) ((x)->pb_flags &= ~PBF_FLUSH) +#define XFS_BUF_ISFLUSH(x) ((x)->pb_flags & PBF_FLUSH) + +#define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") +#define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") +#define XFS_BUF_ISSHUT(x) (0) + +#define XFS_BUF_HOLD(x) pagebuf_hold(x) +#define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ) +#define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ) +#define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ) + +#define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE) +#define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE) +#define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE) + +#define XFS_BUF_ISUNINITIAL(x) (0) +#define XFS_BUF_UNUNINITIAL(x) (0) + +#define XFS_BUF_BP_ISMAPPED(bp) 1 + +typedef struct page_buf_s xfs_buf_t; +#define xfs_buf page_buf_s + +typedef struct pb_target xfs_buftarg_t; +#define xfs_buftarg pb_target + +#define XFS_BUF_DATAIO(x) ((x)->pb_flags |= PBF_FS_DATAIOD) +#define XFS_BUF_UNDATAIO(x) ((x)->pb_flags &= ~PBF_FS_DATAIOD) + +#define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone +#define XFS_BUF_SET_IODONE_FUNC(buf, func) \ + (buf)->pb_iodone = (func) +#define XFS_BUF_CLR_IODONE_FUNC(buf) \ + (buf)->pb_iodone = NULL +#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \ + (buf)->pb_strat = (func) +#define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \ + (buf)->pb_strat = NULL + +#define XFS_BUF_FSPRIVATE(buf, type) \ + ((type)(buf)->pb_fspriv) +#define XFS_BUF_SET_FSPRIVATE(buf, value) \ + (buf)->pb_fspriv = (void *)(value) +#define XFS_BUF_FSPRIVATE2(buf, type) \ + ((type)(buf)->pb_fspriv2) +#define XFS_BUF_SET_FSPRIVATE2(buf, value) \ + (buf)->pb_fspriv2 = (void *)(value) +#define XFS_BUF_FSPRIVATE3(buf, type) \ + ((type)(buf)->pb_fspriv3) +#define XFS_BUF_SET_FSPRIVATE3(buf, value) \ + (buf)->pb_fspriv3 = (void *)(value) +#define XFS_BUF_SET_START(buf) + +#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \ + (buf)->pb_relse = (value) + +#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr) + +extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset) +{ + if (bp->pb_flags & PBF_MAPPED) + return XFS_BUF_PTR(bp) + offset; + return (xfs_caddr_t) pagebuf_offset(bp, offset); +} + +#define XFS_BUF_SET_PTR(bp, val, count) \ + pagebuf_associate_memory(bp, val, count) +#define XFS_BUF_ADDR(bp) ((bp)->pb_bn) +#define XFS_BUF_SET_ADDR(bp, blk) \ + ((bp)->pb_bn = (page_buf_daddr_t)(blk)) +#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) +#define XFS_BUF_SET_OFFSET(bp, off) \ + ((bp)->pb_file_offset = (off)) +#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) +#define XFS_BUF_SET_COUNT(bp, cnt) \ + ((bp)->pb_count_desired = (cnt)) +#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) +#define XFS_BUF_SET_SIZE(bp, cnt) \ + ((bp)->pb_buffer_length = (cnt)) +#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) +#define XFS_BUF_SET_VTYPE(bp, type) +#define XFS_BUF_SET_REF(bp, ref) + +#define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp) + +#define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp) +#define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0) +#define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp) +#define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp) +#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema); + +/* setup the buffer target from a buftarg structure */ +#define XFS_BUF_SET_TARGET(bp, target) \ + (bp)->pb_target = (target) +#define XFS_BUF_TARGET(bp) ((bp)->pb_target) +#define XFS_BUFTARG_NAME(target) \ + pagebuf_target_name(target) + +#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) +#define XFS_BUF_SET_VTYPE(bp, type) +#define XFS_BUF_SET_REF(bp, ref) + +#define xfs_buf_read(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE) +#define xfs_buf_get(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE) + +#define xfs_buf_read_flags(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_READ | PBF_MAPPABLE | flags) +#define xfs_buf_get_flags(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_MAPPABLE | flags) + +static inline int xfs_bawrite(void *mp, page_buf_t *bp) +{ + bp->pb_fspriv3 = mp; + bp->pb_strat = xfs_bdstrat_cb; + xfs_buf_undelay(bp); + return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES); +} + +static inline void xfs_buf_relse(page_buf_t *bp) +{ + if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse) + pagebuf_unlock(bp); + pagebuf_rele(bp); +} + +#define xfs_bpin(bp) pagebuf_pin(bp) +#define xfs_bunpin(bp) pagebuf_unpin(bp) + +#define xfs_buftrace(id, bp) \ + pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) + +#define xfs_biodone(pb) \ + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0) + +#define xfs_incore(buftarg,blkno,len,lockit) \ + pagebuf_find(buftarg, blkno ,len, lockit) + + +#define xfs_biomove(pb, off, len, data, rw) \ + pagebuf_iomove((pb), (off), (len), (data), \ + ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ) + +#define xfs_biozero(pb, off, len) \ + pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO) + + +static inline int XFS_bwrite(page_buf_t *pb) +{ + int iowait = (pb->pb_flags & PBF_ASYNC) == 0; + int error = 0; + + pb->pb_flags |= PBF_SYNC; + if (!iowait) + pb->pb_flags |= PBF_RUN_QUEUES; + + xfs_buf_undelay(pb); + pagebuf_iostrategy(pb); + if (iowait) { + error = pagebuf_iowait(pb); + xfs_buf_relse(pb); + } + return error; +} + +#define XFS_bdwrite(pb) \ + pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC) + +static inline int xfs_bdwrite(void *mp, page_buf_t *bp) +{ + bp->pb_strat = xfs_bdstrat_cb; + bp->pb_fspriv3 = mp; + + return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC); +} + +#define XFS_bdstrat(bp) pagebuf_iorequest(bp) + +#define xfs_iowait(pb) pagebuf_iowait(pb) + + +/* + * Go through all incore buffers, and release buffers + * if they belong to the given device. This is used in + * filesystem error handling to preserve the consistency + * of its metadata. + */ + +#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg) + +#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg) + +#define xfs_incore_relse(buftarg,delwri_only,wait) \ + xfs_relse_buftarg(buftarg) + +#define xfs_baread(target, rablkno, ralen) \ + pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK) + +#define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target)) +#define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target)) +#define xfs_buf_free(bp) pagebuf_free(bp) + +#endif /* __XFS_BUF_H__ */ + diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_globals.c linux-2.6.2-rc3/fs/xfs/linux/xfs_globals.c --- linux-2.6.2-rc2/fs/xfs/linux/xfs_globals.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_globals.c 2004-01-30 18:49:23.000000000 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -36,57 +36,8 @@ */ #include "xfs.h" - -#include "xfs_fs.h" -#include "xfs_buf.h" -#include "xfs_inum.h" -#include "xfs_log.h" -#include "xfs_clnt.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_ag.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_imap.h" -#include "xfs_alloc.h" -#include "xfs_dmapi.h" -#include "xfs_quota.h" -#include "xfs_mount.h" -#include "xfs_alloc_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" -#include "xfs_ialloc.h" -#include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_bit.h" -#include "xfs_rtalloc.h" -#include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_rw.h" -#include "xfs_da_btree.h" -#include "xfs_dir_leaf.h" -#include "xfs_dir2_data.h" -#include "xfs_dir2_leaf.h" -#include "xfs_dir2_block.h" -#include "xfs_dir2_node.h" -#include "xfs_dir2_trace.h" -#include "xfs_acl.h" -#include "xfs_cap.h" -#include "xfs_mac.h" -#include "xfs_attr.h" -#include "xfs_attr_leaf.h" -#include "xfs_inode_item.h" -#include "xfs_buf_item.h" -#include "xfs_extfree_item.h" -#include "xfs_log_priv.h" -#include "xfs_trans_priv.h" -#include "xfs_trans_space.h" -#include "xfs_utils.h" +#include "xfs_cred.h" +#include "xfs_sysctl.h" /* * System memory size - used to scale certain data structures in XFS. @@ -117,34 +68,3 @@ */ cred_t sys_cred_val, *sys_cred = &sys_cred_val; -/* - * Export symbols used for XFS debugging - */ -EXPORT_SYMBOL(xfs_next_bit); -EXPORT_SYMBOL(xfs_contig_bits); -EXPORT_SYMBOL(xfs_bmbt_get_all); -#if ARCH_CONVERT != ARCH_NOCONVERT -EXPORT_SYMBOL(xfs_bmbt_disk_get_all); -#endif - -/* - * Export symbols used for XFS tracing - */ -#ifdef XFS_ALLOC_TRACE -EXPORT_SYMBOL(xfs_alloc_trace_buf); -#endif -#ifdef XFS_BMAP_TRACE -EXPORT_SYMBOL(xfs_bmap_trace_buf); -#endif -#ifdef XFS_BMBT_TRACE -EXPORT_SYMBOL(xfs_bmbt_trace_buf); -#endif -#ifdef XFS_ATTR_TRACE -EXPORT_SYMBOL(xfs_attr_trace_buf); -#endif -#ifdef XFS_DIR2_TRACE -EXPORT_SYMBOL(xfs_dir2_trace_buf); -#endif -#ifdef XFS_DIR_TRACE -EXPORT_SYMBOL(xfs_dir_trace_buf); -#endif diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_iomap.c linux-2.6.2-rc3/fs/xfs/linux/xfs_iomap.c --- linux-2.6.2-rc2/fs/xfs/linux/xfs_iomap.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_iomap.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,795 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#include "xfs.h" - -#include "xfs_fs.h" -#include "xfs_inum.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_ag.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_alloc.h" -#include "xfs_dmapi.h" -#include "xfs_quota.h" -#include "xfs_mount.h" -#include "xfs_alloc_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" -#include "xfs_ialloc.h" -#include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_bit.h" -#include "xfs_rtalloc.h" -#include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_rw.h" -#include "xfs_acl.h" -#include "xfs_cap.h" -#include "xfs_mac.h" -#include "xfs_attr.h" -#include "xfs_buf_item.h" -#include "xfs_trans_space.h" -#include "xfs_utils.h" -#include "xfs_iomap.h" - -#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ - << mp->m_writeio_log) -#define XFS_STRAT_WRITE_IMAPS 2 -#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP - -STATIC int -xfs_imap_to_bmap( - xfs_iocore_t *io, - xfs_off_t offset, - xfs_bmbt_irec_t *imap, - xfs_iomap_t *iomapp, - int imaps, /* Number of imap entries */ - int iomaps, /* Number of iomap entries */ - int flags) -{ - xfs_mount_t *mp; - xfs_fsize_t nisize; - int pbm; - xfs_fsblock_t start_block; - - mp = io->io_mount; - nisize = XFS_SIZE(mp, io); - if (io->io_new_size > nisize) - nisize = io->io_new_size; - - for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { - iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? - mp->m_rtdev_targp : mp->m_ddev_targp; - iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); - iomapp->iomap_delta = offset - iomapp->iomap_offset; - iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); - iomapp->iomap_flags = flags; - - start_block = imap->br_startblock; - if (start_block == HOLESTARTBLOCK) { - iomapp->iomap_bn = IOMAP_DADDR_NULL; - iomapp->iomap_flags = IOMAP_HOLE; - } else if (start_block == DELAYSTARTBLOCK) { - iomapp->iomap_bn = IOMAP_DADDR_NULL; - iomapp->iomap_flags = IOMAP_DELAY; - } else { - iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); - if (ISUNWRITTEN(imap)) - iomapp->iomap_flags |= IOMAP_UNWRITTEN; - } - - if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) { - iomapp->iomap_flags |= IOMAP_EOF; - } - - offset += iomapp->iomap_bsize - iomapp->iomap_delta; - } - return pbm; /* Return the number filled */ -} - -int -xfs_iomap( - xfs_iocore_t *io, - xfs_off_t offset, - ssize_t count, - int flags, - xfs_iomap_t *iomapp, - int *niomaps) -{ - xfs_mount_t *mp = io->io_mount; - xfs_fileoff_t offset_fsb, end_fsb; - int error = 0; - int lockmode = 0; - xfs_bmbt_irec_t imap; - int nimaps = 1; - int bmapi_flags = 0; - int iomap_flags = 0; - - if (XFS_FORCED_SHUTDOWN(mp)) - return XFS_ERROR(EIO); - - switch (flags & - (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | - BMAPI_UNWRITTEN | BMAPI_DEVICE)) { - case BMAPI_READ: - lockmode = XFS_LCK_MAP_SHARED(mp, io); - bmapi_flags = XFS_BMAPI_ENTIRE; - if (flags & BMAPI_IGNSTATE) - bmapi_flags |= XFS_BMAPI_IGSTATE; - break; - case BMAPI_WRITE: - lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; - bmapi_flags = 0; - XFS_ILOCK(mp, io, lockmode); - break; - case BMAPI_ALLOCATE: - lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; - bmapi_flags = XFS_BMAPI_ENTIRE; - /* Attempt non-blocking lock */ - if (flags & BMAPI_TRYLOCK) { - if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) - return XFS_ERROR(EAGAIN); - } else { - XFS_ILOCK(mp, io, lockmode); - } - break; - case BMAPI_UNWRITTEN: - goto phase2; - case BMAPI_DEVICE: - lockmode = XFS_LCK_MAP_SHARED(mp, io); - iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? - mp->m_rtdev_targp : mp->m_ddev_targp; - error = 0; - *niomaps = 1; - goto out; - default: - BUG(); - } - - ASSERT(offset <= mp->m_maxioffset); - if ((xfs_fsize_t)offset + count > mp->m_maxioffset) - count = mp->m_maxioffset - offset; - end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); - offset_fsb = XFS_B_TO_FSBT(mp, offset); - - error = XFS_BMAPI(mp, NULL, io, offset_fsb, - (xfs_filblks_t)(end_fsb - offset_fsb), - bmapi_flags, NULL, 0, &imap, - &nimaps, NULL); - - if (error) - goto out; - -phase2: - switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { - case BMAPI_WRITE: - /* If we found an extent, return it */ - if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) - break; - - if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { - error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, - count, flags, &imap, &nimaps, nimaps); - } else { - error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, - flags, &imap, &nimaps); - } - iomap_flags = IOMAP_NEW; - break; - case BMAPI_ALLOCATE: - /* If we found an extent, return it */ - XFS_IUNLOCK(mp, io, lockmode); - lockmode = 0; - - if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) - break; - - error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); - break; - case BMAPI_UNWRITTEN: - lockmode = 0; - error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); - nimaps = 0; - break; - } - - if (nimaps) { - *niomaps = xfs_imap_to_bmap(io, offset, &imap, - iomapp, nimaps, *niomaps, iomap_flags); - } else if (niomaps) { - *niomaps = 0; - } - -out: - if (lockmode) - XFS_IUNLOCK(mp, io, lockmode); - return XFS_ERROR(error); -} - -STATIC int -xfs_flush_space( - xfs_inode_t *ip, - int *fsynced, - int *ioflags) -{ - switch (*fsynced) { - case 0: - if (ip->i_delayed_blks) { - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_flush_inode(ip); - xfs_ilock(ip, XFS_ILOCK_EXCL); - *fsynced = 1; - } else { - *ioflags |= BMAPI_SYNC; - *fsynced = 2; - } - return 0; - case 1: - *fsynced = 2; - *ioflags |= BMAPI_SYNC; - return 0; - case 2: - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_flush_device(ip); - xfs_ilock(ip, XFS_ILOCK_EXCL); - *fsynced = 3; - return 0; - } - return 1; -} - -int -xfs_iomap_write_direct( - xfs_inode_t *ip, - loff_t offset, - size_t count, - int flags, - xfs_bmbt_irec_t *ret_imap, - int *nmaps, - int found) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_iocore_t *io = &ip->i_iocore; - xfs_fileoff_t offset_fsb; - xfs_fileoff_t last_fsb; - xfs_filblks_t count_fsb; - xfs_fsize_t isize; - xfs_fsblock_t firstfsb; - int nimaps, maps; - int error; - int bmapi_flag; - int rt; - xfs_trans_t *tp; - xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; - xfs_bmap_free_t free_list; - int aeof; - xfs_filblks_t datablocks; - int committed; - int numrtextents; - uint resblks; - - /* - * Make sure that the dquots are there. This doesn't hold - * the ilock across a disk read. - */ - - error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); - if (error) - return XFS_ERROR(error); - - maps = min(XFS_WRITE_IMAPS, *nmaps); - nimaps = maps; - - isize = ip->i_d.di_size; - aeof = (offset + count) > isize; - - if (io->io_new_size > isize) - isize = io->io_new_size; - - offset_fsb = XFS_B_TO_FSBT(mp, offset); - last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); - count_fsb = last_fsb - offset_fsb; - if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { - xfs_fileoff_t map_last_fsb; - - map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; - - if (map_last_fsb < last_fsb) { - last_fsb = map_last_fsb; - count_fsb = last_fsb - offset_fsb; - } - ASSERT(count_fsb > 0); - } - - /* - * determine if reserving space on - * the data or realtime partition. - */ - if ((rt = XFS_IS_REALTIME_INODE(ip))) { - int sbrtextsize, iprtextsize; - - sbrtextsize = mp->m_sb.sb_rextsize; - iprtextsize = - ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; - numrtextents = (count_fsb + iprtextsize - 1); - do_div(numrtextents, sbrtextsize); - datablocks = 0; - } else { - datablocks = count_fsb; - numrtextents = 0; - } - - /* - * allocate and setup the transaction - */ - xfs_iunlock(ip, XFS_ILOCK_EXCL); - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - - resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); - - error = xfs_trans_reserve(tp, resblks, - XFS_WRITE_LOG_RES(mp), numrtextents, - XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - - /* - * check for running out of space - */ - if (error) - /* - * Free the transaction structure. - */ - xfs_trans_cancel(tp, 0); - - xfs_ilock(ip, XFS_ILOCK_EXCL); - - if (error) - goto error_out; /* Don't return in above if .. trans .., - need lock to return */ - - if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { - error = (EDQUOT); - goto error1; - } - nimaps = 1; - - bmapi_flag = XFS_BMAPI_WRITE; - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, ip); - - if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) - bmapi_flag |= XFS_BMAPI_PREALLOC; - - /* - * issue the bmapi() call to allocate the blocks - */ - XFS_BMAP_INIT(&free_list, &firstfsb); - imapp = &imap[0]; - error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, - bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); - if (error) { - goto error0; - } - - /* - * complete the transaction - */ - - error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); - if (error) { - goto error0; - } - - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - if (error) { - goto error_out; - } - - /* copy any maps to caller's array and return any error. */ - if (nimaps == 0) { - error = (ENOSPC); - goto error_out; - } - - *ret_imap = imap[0]; - *nmaps = 1; - return 0; - - error0: /* Cancel bmap, unlock inode, and cancel trans */ - xfs_bmap_cancel(&free_list); - - error1: /* Just cancel transaction */ - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - *nmaps = 0; /* nothing set-up here */ - -error_out: - return XFS_ERROR(error); -} - -int -xfs_iomap_write_delay( - xfs_inode_t *ip, - loff_t offset, - size_t count, - int ioflag, - xfs_bmbt_irec_t *ret_imap, - int *nmaps) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_iocore_t *io = &ip->i_iocore; - xfs_fileoff_t offset_fsb; - xfs_fileoff_t last_fsb; - xfs_fsize_t isize; - xfs_fsblock_t firstblock; - int nimaps; - int error; - xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; - int aeof; - int fsynced = 0; - - ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); - - /* - * Make sure that the dquots are there. This doesn't hold - * the ilock across a disk read. - */ - - error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); - if (error) - return XFS_ERROR(error); - -retry: - isize = ip->i_d.di_size; - if (io->io_new_size > isize) { - isize = io->io_new_size; - } - - aeof = 0; - offset_fsb = XFS_B_TO_FSBT(mp, offset); - last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); - /* - * If the caller is doing a write at the end of the file, - * then extend the allocation (and the buffer used for the write) - * out to the file system's write iosize. We clean up any extra - * space left over when the file is closed in xfs_inactive(). - * - * We don't bother with this for sync writes, because we need - * to minimize the amount we write for good performance. - */ - if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { - xfs_off_t aligned_offset; - unsigned int iosize; - xfs_fileoff_t ioalign; - - iosize = mp->m_writeio_blocks; - aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); - ioalign = XFS_B_TO_FSBT(mp, aligned_offset); - last_fsb = ioalign + iosize; - aeof = 1; - } - - nimaps = XFS_WRITE_IMAPS; - firstblock = NULLFSBLOCK; - - /* - * roundup the allocation request to m_dalign boundary if file size - * is greater that 512K and we are allocating past the allocation eof - */ - if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) { - int eof; - xfs_fileoff_t new_last_fsb; - new_last_fsb = roundup_64(last_fsb, mp->m_dalign); - error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); - if (error) { - return error; - } - if (eof) { - last_fsb = new_last_fsb; - } - } - - error = xfs_bmapi(NULL, ip, offset_fsb, - (xfs_filblks_t)(last_fsb - offset_fsb), - XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | - XFS_BMAPI_ENTIRE, &firstblock, 1, imap, - &nimaps, NULL); - /* - * This can be EDQUOT, if nimaps == 0 - */ - if (error && (error != ENOSPC)) { - return XFS_ERROR(error); - } - /* - * If bmapi returned us nothing, and if we didn't get back EDQUOT, - * then we must have run out of space. - */ - - if (nimaps == 0) { - if (xfs_flush_space(ip, &fsynced, &ioflag)) - return XFS_ERROR(ENOSPC); - - error = 0; - goto retry; - } - - *ret_imap = imap[0]; - *nmaps = 1; - return 0; -} - -/* - * Pass in a delayed allocate extent, convert it to real extents; - * return to the caller the extent we create which maps on top of - * the originating callers request. - * - * Called without a lock on the inode. - */ -int -xfs_iomap_write_allocate( - xfs_inode_t *ip, - xfs_bmbt_irec_t *map, - int *retmap) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_fileoff_t offset_fsb, last_block; - xfs_fileoff_t end_fsb, map_start_fsb; - xfs_fsblock_t first_block; - xfs_bmap_free_t free_list; - xfs_filblks_t count_fsb; - xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS]; - xfs_trans_t *tp; - int i, nimaps, committed; - int error = 0; - int nres; - - *retmap = 0; - - /* - * Make sure that the dquots are there. - */ - - if ((error = XFS_QM_DQATTACH(mp, ip, 0))) - return XFS_ERROR(error); - - offset_fsb = map->br_startoff; - count_fsb = map->br_blockcount; - map_start_fsb = offset_fsb; - - XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); - - while (count_fsb != 0) { - /* - * Set up a transaction with which to allocate the - * backing store for the file. Do allocations in a - * loop until we get some space in the range we are - * interested in. The other space that might be allocated - * is in the delayed allocation extent on which we sit - * but before our buffer starts. - */ - - nimaps = 0; - while (nimaps == 0) { - tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); - error = xfs_trans_reserve(tp, nres, - XFS_WRITE_LOG_RES(mp), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - - if (error == ENOSPC) { - error = xfs_trans_reserve(tp, 0, - XFS_WRITE_LOG_RES(mp), - 0, - XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - } - if (error) { - xfs_trans_cancel(tp, 0); - return XFS_ERROR(error); - } - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, ip); - - XFS_BMAP_INIT(&free_list, &first_block); - - nimaps = XFS_STRAT_WRITE_IMAPS; - /* - * Ensure we don't go beyond eof - it is possible - * the extents changed since we did the read call, - * we dropped the ilock in the interim. - */ - - end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size); - xfs_bmap_last_offset(NULL, ip, &last_block, - XFS_DATA_FORK); - last_block = XFS_FILEOFF_MAX(last_block, end_fsb); - if ((map_start_fsb + count_fsb) > last_block) { - count_fsb = last_block - map_start_fsb; - if (count_fsb == 0) { - error = EAGAIN; - goto trans_cancel; - } - } - - /* Go get the actual blocks */ - error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, - XFS_BMAPI_WRITE, &first_block, 1, - imap, &nimaps, &free_list); - - if (error) - goto trans_cancel; - - error = xfs_bmap_finish(&tp, &free_list, - first_block, &committed); - - if (error) - goto trans_cancel; - - error = xfs_trans_commit(tp, - XFS_TRANS_RELEASE_LOG_RES, NULL); - - if (error) - goto error0; - - xfs_iunlock(ip, XFS_ILOCK_EXCL); - } - - /* - * See if we were able to allocate an extent that - * covers at least part of the callers request - */ - - for (i = 0; i < nimaps; i++) { - if ((map->br_startoff >= imap[i].br_startoff) && - (map->br_startoff < (imap[i].br_startoff + - imap[i].br_blockcount))) { - *map = imap[i]; - *retmap = 1; - XFS_STATS_INC(xs_xstrat_quick); - return 0; - } - count_fsb -= imap[i].br_blockcount; - } - - /* So far we have not mapped the requested part of the - * file, just surrounding data, try again. - */ - nimaps--; - offset_fsb = imap[nimaps].br_startoff + - imap[nimaps].br_blockcount; - map_start_fsb = offset_fsb; - } - -trans_cancel: - xfs_bmap_cancel(&free_list); - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); -error0: - xfs_iunlock(ip, XFS_ILOCK_EXCL); - return XFS_ERROR(error); -} - -int -xfs_iomap_write_unwritten( - xfs_inode_t *ip, - loff_t offset, - size_t count) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_trans_t *tp; - xfs_fileoff_t offset_fsb; - xfs_filblks_t count_fsb; - xfs_filblks_t numblks_fsb; - xfs_bmbt_irec_t imap; - int committed; - int error; - int nres; - int nimaps; - xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; - - offset_fsb = XFS_B_TO_FSBT(mp, offset); - count_fsb = XFS_B_TO_FSB(mp, count); - - do { - nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); - - /* - * set up a transaction to convert the range of extents - * from unwritten to real. Do allocations in a loop until - * we have covered the range passed in. - */ - - tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - error = xfs_trans_reserve(tp, nres, - XFS_WRITE_LOG_RES(mp), 0, - XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - if (error) { - xfs_trans_cancel(tp, 0); - goto error0; - } - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, ip); - - /* - * Modify the unwritten extent state of the buffer. - */ - XFS_BMAP_INIT(&free_list, &firstfsb); - nimaps = 1; - error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, - XFS_BMAPI_WRITE, &firstfsb, - 1, &imap, &nimaps, &free_list); - if (error) - goto error_on_bmapi_transaction; - - error = xfs_bmap_finish(&(tp), &(free_list), - firstfsb, &committed); - if (error) - goto error_on_bmapi_transaction; - - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - if (error) - goto error0; - - if ((numblks_fsb = imap.br_blockcount) == 0) { - /* - * The numblks_fsb value should always get - * smaller, otherwise the loop is stuck. - */ - ASSERT(imap.br_blockcount); - break; - } - offset_fsb += numblks_fsb; - count_fsb -= numblks_fsb; - } while (count_fsb > 0); - - return 0; - -error_on_bmapi_transaction: - xfs_bmap_cancel(&free_list); - xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT)); - xfs_iunlock(ip, XFS_ILOCK_EXCL); -error0: - return XFS_ERROR(error); -} diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_linux.h linux-2.6.2-rc3/fs/xfs/linux/xfs_linux.h --- linux-2.6.2-rc2/fs/xfs/linux/xfs_linux.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_linux.h 2004-01-30 18:49:23.000000000 -0800 @@ -32,6 +32,44 @@ #ifndef __XFS_LINUX__ #define __XFS_LINUX__ +#include +#include + +/* + * Some types are conditional depending on the target system. + * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. + * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well + * as requiring XFS_BIG_BLKNOS to be set. + */ +#if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) +# define XFS_BIG_BLKNOS 1 +# if BITS_PER_LONG == 64 +# define XFS_BIG_INUMS 1 +# else +# define XFS_BIG_INUMS 0 +# endif +#else +# define XFS_BIG_BLKNOS 0 +# define XFS_BIG_INUMS 0 +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + #include #include #include @@ -55,19 +93,18 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* * Feature macros (disable/enable) diff -urN linux-2.6.2-rc2/fs/xfs/linux/xfs_super.h linux-2.6.2-rc3/fs/xfs/linux/xfs_super.h --- linux-2.6.2-rc2/fs/xfs/linux/xfs_super.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/linux/xfs_super.h 2004-01-30 18:49:23.000000000 -0800 @@ -60,6 +60,14 @@ # define set_posix_acl_flag(sb) do { } while (0) #endif +#ifdef CONFIG_XFS_SECURITY +# define XFS_SECURITY_STRING "security attrs, " +# define ENOSECURITY 0 +#else +# define XFS_SECURITY_STRING +# define ENOSECURITY EOPNOTSUPP +#endif + #ifdef CONFIG_XFS_RT # define XFS_REALTIME_STRING "realtime, " #else @@ -89,6 +97,7 @@ #endif #define XFS_BUILD_OPTIONS XFS_ACL_STRING \ + XFS_SECURITY_STRING \ XFS_REALTIME_STRING \ XFS_BIGFS_STRING \ XFS_TRACE_STRING \ diff -urN linux-2.6.2-rc2/fs/xfs/pagebuf/page_buf.c linux-2.6.2-rc3/fs/xfs/pagebuf/page_buf.c --- linux-2.6.2-rc2/fs/xfs/pagebuf/page_buf.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/pagebuf/page_buf.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,2107 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -/* - * page_buf.c - * - * The page_buf module provides an abstract buffer cache model on top of - * the Linux page cache. Cached metadata blocks for a file system are - * hashed to the inode for the block device. The page_buf module - * assembles buffer (page_buf_t) objects on demand to aggregate such - * cached pages for I/O. - * - * - * Written by Steve Lord, Jim Mostek, Russell Cattelan - * and Rajagopal Ananthanarayanan ("ananth") at SGI. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "page_buf.h" - -#define BBSHIFT 9 -#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1) - -#ifndef GFP_READAHEAD -#define GFP_READAHEAD (__GFP_NOWARN|__GFP_NORETRY) -#endif - -/* - * File wide globals - */ - -STATIC kmem_cache_t *pagebuf_cache; -STATIC void pagebuf_daemon_wakeup(int); -STATIC void pagebuf_delwri_queue(page_buf_t *, int); -STATIC struct workqueue_struct *pagebuf_logio_workqueue; -STATIC struct workqueue_struct *pagebuf_dataio_workqueue; - -/* - * Pagebuf module configuration parameters, exported via - * /proc/sys/vm/pagebuf - */ - -typedef struct pb_sysctl_val { - int min; - int val; - int max; -} pb_sysctl_val_t; - -struct { - pb_sysctl_val_t flush_interval; /* interval between runs of the - * delwri flush daemon. */ - pb_sysctl_val_t age_buffer; /* time for buffer to age before - * we flush it. */ - pb_sysctl_val_t stats_clear; /* clear the pagebuf stats */ - pb_sysctl_val_t debug; /* debug tracing on or off */ -} pb_params = { - /* MIN DFLT MAX */ - .flush_interval = { HZ/2, HZ, 30*HZ }, - .age_buffer = { 1*HZ, 15*HZ, 300*HZ }, - .stats_clear = { 0, 0, 1 }, - .debug = { 0, 0, 1 }, -}; - -enum { - PB_FLUSH_INT = 1, - PB_FLUSH_AGE = 2, - PB_STATS_CLEAR = 3, - PB_DEBUG = 4, -}; - -/* - * Pagebuf statistics variables - */ - -struct pbstats { - u_int32_t pb_get; - u_int32_t pb_create; - u_int32_t pb_get_locked; - u_int32_t pb_get_locked_waited; - u_int32_t pb_busy_locked; - u_int32_t pb_miss_locked; - u_int32_t pb_page_retries; - u_int32_t pb_page_found; - u_int32_t pb_get_read; -} pbstats; -DEFINE_PER_CPU(struct pbstats, pbstats); - -/* We don't disable preempt, not too worried about poking the - * wrong cpu's stat for now */ -#define PB_STATS_INC(count) (__get_cpu_var(pbstats).count++) - -/* - * Pagebuf debugging - */ - -#ifdef PAGEBUF_TRACE -void -pagebuf_trace( - page_buf_t *pb, - char *id, - void *data, - void *ra) -{ - if (!pb_params.debug.val) - return; - ktrace_enter(pagebuf_trace_buf, - pb, id, - (void *)(unsigned long)pb->pb_flags, - (void *)(unsigned long)pb->pb_hold.counter, - (void *)(unsigned long)pb->pb_sema.count.counter, - (void *)current, - data, ra, - (void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff), - (void *)(unsigned long)(pb->pb_file_offset & 0xffffffff), - (void *)(unsigned long)pb->pb_buffer_length, - NULL, NULL, NULL, NULL, NULL); -} -ktrace_t *pagebuf_trace_buf; -EXPORT_SYMBOL(pagebuf_trace_buf); -#define PAGEBUF_TRACE_SIZE 4096 -#define PB_TRACE(pb, id, data) \ - pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0)) -#else -#define PB_TRACE(pb, id, data) do { } while (0) -#endif - -#ifdef PAGEBUF_LOCK_TRACKING -# define PB_SET_OWNER(pb) ((pb)->pb_last_holder = current->pid) -# define PB_CLEAR_OWNER(pb) ((pb)->pb_last_holder = -1) -# define PB_GET_OWNER(pb) ((pb)->pb_last_holder) -#else -# define PB_SET_OWNER(pb) do { } while (0) -# define PB_CLEAR_OWNER(pb) do { } while (0) -# define PB_GET_OWNER(pb) do { } while (0) -#endif - -/* - * Pagebuf allocation / freeing. - */ - -#define pb_to_gfp(flags) \ - (((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \ - ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) - -#define pagebuf_allocate(flags) \ - kmem_cache_alloc(pagebuf_cache, pb_to_gfp(flags)) -#define pagebuf_deallocate(pb) \ - kmem_cache_free(pagebuf_cache, (pb)); - -/* - * Pagebuf hashing - */ - -#define NBITS 8 -#define NHASH (1<pb_hash_index] - -STATIC int -_bhash( - struct block_device *bdev, - loff_t base) -{ - int bit, hval; - - base >>= 9; - base ^= (unsigned long)bdev / L1_CACHE_BYTES; - for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) { - hval ^= (int)base & (NHASH-1); - base >>= NBITS; - } - return hval; -} - -/* - * Mapping of multi-page buffers into contiguous virtual space - */ - -STATIC void *pagebuf_mapout_locked(page_buf_t *); - -typedef struct a_list { - void *vm_addr; - struct a_list *next; -} a_list_t; - -STATIC a_list_t *as_free_head; -STATIC int as_list_len; -STATIC spinlock_t as_lock = SPIN_LOCK_UNLOCKED; - -/* - * Try to batch vunmaps because they are costly. - */ -STATIC void -free_address( - void *addr) -{ - a_list_t *aentry; - - aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC); - if (aentry) { - spin_lock(&as_lock); - aentry->next = as_free_head; - aentry->vm_addr = addr; - as_free_head = aentry; - as_list_len++; - spin_unlock(&as_lock); - } else { - vunmap(addr); - } -} - -STATIC void -purge_addresses(void) -{ - a_list_t *aentry, *old; - - if (as_free_head == NULL) - return; - - spin_lock(&as_lock); - aentry = as_free_head; - as_free_head = NULL; - as_list_len = 0; - spin_unlock(&as_lock); - - while ((old = aentry) != NULL) { - vunmap(aentry->vm_addr); - aentry = aentry->next; - kfree(old); - } -} - -/* - * Internal pagebuf object manipulation - */ - -STATIC void -_pagebuf_initialize( - page_buf_t *pb, - pb_target_t *target, - loff_t range_base, - size_t range_length, - page_buf_flags_t flags) -{ - /* - * We don't want certain flags to appear in pb->pb_flags. - */ - flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD); - - memset(pb, 0, sizeof(page_buf_t)); - atomic_set(&pb->pb_hold, 1); - init_MUTEX_LOCKED(&pb->pb_iodonesema); - INIT_LIST_HEAD(&pb->pb_list); - INIT_LIST_HEAD(&pb->pb_hash_list); - init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */ - PB_SET_OWNER(pb); - pb->pb_target = target; - pb->pb_file_offset = range_base; - /* - * Set buffer_length and count_desired to the same value initially. - * IO routines should use count_desired, which will be the same in - * most cases but may be reset (e.g. XFS recovery). - */ - pb->pb_buffer_length = pb->pb_count_desired = range_length; - pb->pb_flags = flags | PBF_NONE; - pb->pb_bn = PAGE_BUF_DADDR_NULL; - atomic_set(&pb->pb_pin_count, 0); - init_waitqueue_head(&pb->pb_waiters); - - PB_STATS_INC(pb_create); - PB_TRACE(pb, "initialize", target); -} - -/* - * Allocate a page array capable of holding a specified number - * of pages, and point the page buf at it. - */ -STATIC int -_pagebuf_get_pages( - page_buf_t *pb, - int page_count, - page_buf_flags_t flags) -{ - int gpf_mask = pb_to_gfp(flags); - - /* Make sure that we have a page list */ - if (pb->pb_pages == NULL) { - pb->pb_offset = page_buf_poff(pb->pb_file_offset); - pb->pb_page_count = page_count; - if (page_count <= PB_PAGES) { - pb->pb_pages = pb->pb_page_array; - } else { - pb->pb_pages = kmalloc(sizeof(struct page *) * - page_count, gpf_mask); - if (pb->pb_pages == NULL) - return -ENOMEM; - } - memset(pb->pb_pages, 0, sizeof(struct page *) * page_count); - } - return 0; -} - -/* - * Walk a pagebuf releasing all the pages contained within it. - */ -STATIC inline void -_pagebuf_freepages( - page_buf_t *pb) -{ - int buf_index; - - for (buf_index = 0; buf_index < pb->pb_page_count; buf_index++) { - struct page *page = pb->pb_pages[buf_index]; - - if (page) { - pb->pb_pages[buf_index] = NULL; - page_cache_release(page); - } - } -} - -/* - * _pagebuf_free_object - * - * _pagebuf_free_object releases the contents specified buffer. - * The modification state of any associated pages is left unchanged. - */ -void -_pagebuf_free_object( - pb_hash_t *hash, /* hash bucket for buffer */ - page_buf_t *pb) /* buffer to deallocate */ -{ - page_buf_flags_t pb_flags = pb->pb_flags; - - PB_TRACE(pb, "free_object", 0); - pb->pb_flags |= PBF_FREED; - - if (hash) { - if (!list_empty(&pb->pb_hash_list)) { - hash->pb_count--; - list_del_init(&pb->pb_hash_list); - } - spin_unlock(&hash->pb_hash_lock); - } - - if (!(pb_flags & PBF_FREED)) { - /* release any virtual mapping */ ; - if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { - void *vaddr = pagebuf_mapout_locked(pb); - if (vaddr) { - free_address(vaddr); - } - } - - if (pb->pb_flags & _PBF_MEM_ALLOCATED) { - if (pb->pb_pages) { - /* release the pages in the address list */ - if ((pb->pb_pages[0]) && - (pb->pb_flags & _PBF_MEM_SLAB)) { - kfree(pb->pb_addr); - } else { - _pagebuf_freepages(pb); - } - if (pb->pb_pages != pb->pb_page_array) - kfree(pb->pb_pages); - pb->pb_pages = NULL; - } - pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); - } - } - - pagebuf_deallocate(pb); -} - -/* - * _pagebuf_lookup_pages - * - * _pagebuf_lookup_pages finds all pages which match the buffer - * in question and the range of file offsets supplied, - * and builds the page list for the buffer, if the - * page list is not already formed or if not all of the pages are - * already in the list. Invalid pages (pages which have not yet been - * read in from disk) are assigned for any pages which are not found. - */ -STATIC int -_pagebuf_lookup_pages( - page_buf_t *pb, - struct address_space *aspace, - page_buf_flags_t flags) -{ - loff_t next_buffer_offset; - unsigned long page_count, pi, index; - struct page *page; - int gfp_mask, retry_count = 5, rval = 0; - int all_mapped, good_pages, nbytes; - unsigned int blocksize, sectorshift; - size_t size, offset; - - - /* For pagebufs where we want to map an address, do not use - * highmem pages - so that we do not need to use kmap resources - * to access the data. - * - * For pages where the caller has indicated there may be resource - * contention (e.g. called from a transaction) do not flush - * delalloc pages to obtain memory. - */ - - if (flags & PBF_READ_AHEAD) { - gfp_mask = GFP_READAHEAD; - retry_count = 0; - } else if (flags & PBF_DONT_BLOCK) { - gfp_mask = GFP_NOFS; - } else if (flags & PBF_MAPPABLE) { - gfp_mask = GFP_KERNEL; - } else { - gfp_mask = GFP_HIGHUSER; - } - - next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length; - - good_pages = page_count = (page_buf_btoc(next_buffer_offset) - - page_buf_btoct(pb->pb_file_offset)); - - if (pb->pb_flags & _PBF_ALL_PAGES_MAPPED) { - /* Bring pages forward in cache */ - for (pi = 0; pi < page_count; pi++) { - mark_page_accessed(pb->pb_pages[pi]); - } - if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) { - all_mapped = 1; - goto mapit; - } - return 0; - } - - /* Ensure pb_pages field has been initialised */ - rval = _pagebuf_get_pages(pb, page_count, flags); - if (rval) - return rval; - - rval = pi = 0; - blocksize = pb->pb_target->pbr_bsize; - sectorshift = pb->pb_target->pbr_sshift; - size = pb->pb_count_desired; - offset = pb->pb_offset; - - /* Enter the pages in the page list */ - index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT; - for (all_mapped = 1; pi < page_count; pi++, index++) { - if (pb->pb_pages[pi] == 0) { - retry: - page = find_or_create_page(aspace, index, gfp_mask); - if (!page) { - if (--retry_count > 0) { - PB_STATS_INC(pb_page_retries); - pagebuf_daemon_wakeup(1); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(10); - goto retry; - } - rval = -ENOMEM; - all_mapped = 0; - continue; - } - PB_STATS_INC(pb_page_found); - mark_page_accessed(page); - pb->pb_pages[pi] = page; - } else { - page = pb->pb_pages[pi]; - lock_page(page); - } - - nbytes = PAGE_CACHE_SIZE - offset; - if (nbytes > size) - nbytes = size; - size -= nbytes; - - if (!PageUptodate(page)) { - if (blocksize == PAGE_CACHE_SIZE) { - if (flags & PBF_READ) - pb->pb_locked = 1; - good_pages--; - } else if (!PagePrivate(page)) { - unsigned long i, range; - - /* - * In this case page->private holds a bitmap - * of uptodate sectors within the page - */ - ASSERT(blocksize < PAGE_CACHE_SIZE); - range = (offset + nbytes) >> sectorshift; - for (i = offset >> sectorshift; i < range; i++) - if (!test_bit(i, &page->private)) - break; - if (i != range) - good_pages--; - } else { - good_pages--; - } - } - offset = 0; - } - - if (!pb->pb_locked) { - for (pi = 0; pi < page_count; pi++) { - if (pb->pb_pages[pi]) - unlock_page(pb->pb_pages[pi]); - } - } - -mapit: - pb->pb_flags |= _PBF_MEM_ALLOCATED; - if (all_mapped) { - pb->pb_flags |= _PBF_ALL_PAGES_MAPPED; - - /* A single page buffer is always mappable */ - if (page_count == 1) { - pb->pb_addr = (caddr_t) - page_address(pb->pb_pages[0]) + pb->pb_offset; - pb->pb_flags |= PBF_MAPPED; - } else if (flags & PBF_MAPPED) { - if (as_list_len > 64) - purge_addresses(); - pb->pb_addr = vmap(pb->pb_pages, page_count, - VM_MAP, PAGE_KERNEL); - if (pb->pb_addr == NULL) - return -ENOMEM; - pb->pb_addr += pb->pb_offset; - pb->pb_flags |= PBF_MAPPED | _PBF_ADDR_ALLOCATED; - } - } - /* If some pages were found with data in them - * we are not in PBF_NONE state. - */ - if (good_pages != 0) { - pb->pb_flags &= ~(PBF_NONE); - if (good_pages != page_count) { - pb->pb_flags |= PBF_PARTIAL; - } - } - - PB_TRACE(pb, "lookup_pages", (long)good_pages); - - return rval; -} - -/* - * Finding and Reading Buffers - */ - -/* - * _pagebuf_find - * - * Looks up, and creates if absent, a lockable buffer for - * a given range of an inode. The buffer is returned - * locked. If other overlapping buffers exist, they are - * released before the new buffer is created and locked, - * which may imply that this call will block until those buffers - * are unlocked. No I/O is implied by this call. - */ -STATIC page_buf_t * -_pagebuf_find( /* find buffer for block */ - pb_target_t *target,/* target for block */ - loff_t ioff, /* starting offset of range */ - size_t isize, /* length of range */ - page_buf_flags_t flags, /* PBF_TRYLOCK */ - page_buf_t *new_pb)/* newly allocated buffer */ -{ - loff_t range_base; - size_t range_length; - int hval; - pb_hash_t *h; - struct list_head *p; - page_buf_t *pb; - int not_locked; - - range_base = (ioff << BBSHIFT); - range_length = (isize << BBSHIFT); - - /* Ensure we never do IOs smaller than the sector size */ - BUG_ON(range_length < (1 << target->pbr_sshift)); - - /* Ensure we never do IOs that are not sector aligned */ - BUG_ON(range_base & (loff_t)target->pbr_smask); - - hval = _bhash(target->pbr_bdev, range_base); - h = &pbhash[hval]; - - spin_lock(&h->pb_hash_lock); - list_for_each(p, &h->pb_hash) { - pb = list_entry(p, page_buf_t, pb_hash_list); - - if ((target == pb->pb_target) && - (pb->pb_file_offset == range_base) && - (pb->pb_buffer_length == range_length)) { - if (pb->pb_flags & PBF_FREED) - break; - /* If we look at something bring it to the - * front of the list for next time - */ - list_del(&pb->pb_hash_list); - list_add(&pb->pb_hash_list, &h->pb_hash); - goto found; - } - } - - /* No match found */ - if (new_pb) { - _pagebuf_initialize(new_pb, target, range_base, - range_length, flags | _PBF_LOCKABLE); - new_pb->pb_hash_index = hval; - h->pb_count++; - list_add(&new_pb->pb_hash_list, &h->pb_hash); - } else { - PB_STATS_INC(pb_miss_locked); - } - - spin_unlock(&h->pb_hash_lock); - return (new_pb); - -found: - atomic_inc(&pb->pb_hold); - spin_unlock(&h->pb_hash_lock); - - /* Attempt to get the semaphore without sleeping, - * if this does not work then we need to drop the - * spinlock and do a hard attempt on the semaphore. - */ - not_locked = down_trylock(&pb->pb_sema); - if (not_locked) { - if (!(flags & PBF_TRYLOCK)) { - /* wait for buffer ownership */ - PB_TRACE(pb, "get_lock", 0); - pagebuf_lock(pb); - PB_STATS_INC(pb_get_locked_waited); - } else { - /* We asked for a trylock and failed, no need - * to look at file offset and length here, we - * know that this pagebuf at least overlaps our - * pagebuf and is locked, therefore our buffer - * either does not exist, or is this buffer - */ - - pagebuf_rele(pb); - PB_STATS_INC(pb_busy_locked); - return (NULL); - } - } else { - /* trylock worked */ - PB_SET_OWNER(pb); - } - - if (pb->pb_flags & PBF_STALE) - pb->pb_flags &= PBF_MAPPABLE | \ - PBF_MAPPED | \ - _PBF_LOCKABLE | \ - _PBF_ALL_PAGES_MAPPED | \ - _PBF_ADDR_ALLOCATED | \ - _PBF_MEM_ALLOCATED | \ - _PBF_MEM_SLAB; - PB_TRACE(pb, "got_lock", 0); - PB_STATS_INC(pb_get_locked); - return (pb); -} - - -/* - * pagebuf_find - * - * pagebuf_find returns a buffer matching the specified range of - * data for the specified target, if any of the relevant blocks - * are in memory. The buffer may have unallocated holes, if - * some, but not all, of the blocks are in memory. Even where - * pages are present in the buffer, not all of every page may be - * valid. - */ -page_buf_t * -pagebuf_find( /* find buffer for block */ - /* if the block is in memory */ - pb_target_t *target,/* target for block */ - loff_t ioff, /* starting offset of range */ - size_t isize, /* length of range */ - page_buf_flags_t flags) /* PBF_TRYLOCK */ -{ - return _pagebuf_find(target, ioff, isize, flags, NULL); -} - -/* - * pagebuf_get - * - * pagebuf_get assembles a buffer covering the specified range. - * Some or all of the blocks in the range may be valid. Storage - * in memory for all portions of the buffer will be allocated, - * although backing storage may not be. If PBF_READ is set in - * flags, pagebuf_iostart is called also. - */ -page_buf_t * -pagebuf_get( /* allocate a buffer */ - pb_target_t *target,/* target for buffer */ - loff_t ioff, /* starting offset of range */ - size_t isize, /* length of range */ - page_buf_flags_t flags) /* PBF_TRYLOCK */ -{ - page_buf_t *pb, *new_pb; - int error; - - new_pb = pagebuf_allocate(flags); - if (unlikely(!new_pb)) - return (NULL); - - pb = _pagebuf_find(target, ioff, isize, flags, new_pb); - if (pb != new_pb) { - pagebuf_deallocate(new_pb); - if (unlikely(!pb)) - return (NULL); - } - - PB_STATS_INC(pb_get); - - /* fill in any missing pages */ - error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags); - if (unlikely(error)) { - pagebuf_free(pb); - return (NULL); - } - - /* - * Always fill in the block number now, the mapped cases can do - * their own overlay of this later. - */ - pb->pb_bn = ioff; - pb->pb_count_desired = pb->pb_buffer_length; - - if (flags & PBF_READ) { - if (PBF_NOT_DONE(pb)) { - PB_TRACE(pb, "get_read", (unsigned long)flags); - PB_STATS_INC(pb_get_read); - pagebuf_iostart(pb, flags); - } else if (flags & PBF_ASYNC) { - PB_TRACE(pb, "get_read_async", (unsigned long)flags); - /* - * Read ahead call which is already satisfied, - * drop the buffer - */ - if (flags & (PBF_LOCK | PBF_TRYLOCK)) - pagebuf_unlock(pb); - pagebuf_rele(pb); - return NULL; - } else { - PB_TRACE(pb, "get_read_done", (unsigned long)flags); - /* We do not want read in the flags */ - pb->pb_flags &= ~PBF_READ; - } - } else { - PB_TRACE(pb, "get_write", (unsigned long)flags); - } - return (pb); -} - -/* - * Create a skeletal pagebuf (no pages associated with it). - */ -page_buf_t * -pagebuf_lookup( - struct pb_target *target, - loff_t ioff, - size_t isize, - page_buf_flags_t flags) -{ - page_buf_t *pb; - - pb = pagebuf_allocate(flags); - if (pb) { - _pagebuf_initialize(pb, target, ioff, isize, flags); - } - return pb; -} - -/* - * If we are not low on memory then do the readahead in a deadlock - * safe manner. - */ -void -pagebuf_readahead( - pb_target_t *target, - loff_t ioff, - size_t isize, - page_buf_flags_t flags) -{ - struct backing_dev_info *bdi; - - bdi = target->pbr_mapping->backing_dev_info; - if (bdi_read_congested(bdi)) - return; - if (bdi_write_congested(bdi)) - return; - - flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD); - pagebuf_get(target, ioff, isize, flags); -} - -page_buf_t * -pagebuf_get_empty( - size_t len, - pb_target_t *target) -{ - page_buf_t *pb; - - pb = pagebuf_allocate(_PBF_LOCKABLE); - if (pb) - _pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE); - return pb; -} - -static inline struct page * -mem_to_page( - void *addr) -{ - if (((unsigned long)addr < VMALLOC_START) || - ((unsigned long)addr >= VMALLOC_END)) { - return virt_to_page(addr); - } else { - return vmalloc_to_page(addr); - } -} - -int -pagebuf_associate_memory( - page_buf_t *pb, - void *mem, - size_t len) -{ - int rval; - int i = 0; - size_t ptr; - size_t end, end_cur; - off_t offset; - int page_count; - - page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; - offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK); - if (offset && (len > PAGE_CACHE_SIZE)) - page_count++; - - /* Free any previous set of page pointers */ - if (pb->pb_pages && (pb->pb_pages != pb->pb_page_array)) { - kfree(pb->pb_pages); - } - pb->pb_pages = NULL; - pb->pb_addr = mem; - - rval = _pagebuf_get_pages(pb, page_count, 0); - if (rval) - return rval; - - pb->pb_offset = offset; - ptr = (size_t) mem & PAGE_CACHE_MASK; - end = PAGE_CACHE_ALIGN((size_t) mem + len); - end_cur = end; - /* set up first page */ - pb->pb_pages[0] = mem_to_page(mem); - - ptr += PAGE_CACHE_SIZE; - pb->pb_page_count = ++i; - while (ptr < end) { - pb->pb_pages[i] = mem_to_page((void *)ptr); - pb->pb_page_count = ++i; - ptr += PAGE_CACHE_SIZE; - } - pb->pb_locked = 0; - - pb->pb_count_desired = pb->pb_buffer_length = len; - pb->pb_flags |= PBF_MAPPED; - - return 0; -} - -page_buf_t * -pagebuf_get_no_daddr( - size_t len, - pb_target_t *target) -{ - int rval; - void *rmem = NULL; - page_buf_flags_t flags = _PBF_LOCKABLE | PBF_FORCEIO; - page_buf_t *pb; - size_t tlen = 0; - - if (unlikely(len > 0x20000)) - return NULL; - - pb = pagebuf_allocate(flags); - if (!pb) - return NULL; - - _pagebuf_initialize(pb, target, 0, len, flags); - - do { - if (tlen == 0) { - tlen = len; /* first time */ - } else { - kfree(rmem); /* free the mem from the previous try */ - tlen <<= 1; /* double the size and try again */ - } - if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) { - pagebuf_free(pb); - return NULL; - } - } while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask)); - - if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) { - kfree(rmem); - pagebuf_free(pb); - return NULL; - } - /* otherwise pagebuf_free just ignores it */ - pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB); - PB_CLEAR_OWNER(pb); - up(&pb->pb_sema); /* Return unlocked pagebuf */ - - PB_TRACE(pb, "no_daddr", rmem); - - return pb; -} - - -/* - * pagebuf_hold - * - * Increment reference count on buffer, to hold the buffer concurrently - * with another thread which may release (free) the buffer asynchronously. - * - * Must hold the buffer already to call this function. - */ -void -pagebuf_hold( - page_buf_t *pb) -{ - atomic_inc(&pb->pb_hold); - PB_TRACE(pb, "hold", 0); -} - -/* - * pagebuf_free - * - * pagebuf_free releases the specified buffer. The modification - * state of any associated pages is left unchanged. - */ -void -pagebuf_free( - page_buf_t *pb) -{ - if (pb->pb_flags & _PBF_LOCKABLE) { - pb_hash_t *h = pb_hash(pb); - - spin_lock(&h->pb_hash_lock); - _pagebuf_free_object(h, pb); - } else { - _pagebuf_free_object(NULL, pb); - } -} - -/* - * pagebuf_rele - * - * pagebuf_rele releases a hold on the specified buffer. If the - * the hold count is 1, pagebuf_rele calls pagebuf_free. - */ -void -pagebuf_rele( - page_buf_t *pb) -{ - pb_hash_t *h; - - PB_TRACE(pb, "rele", pb->pb_relse); - if (pb->pb_flags & _PBF_LOCKABLE) { - h = pb_hash(pb); - spin_lock(&h->pb_hash_lock); - } else { - h = NULL; - } - - if (atomic_dec_and_test(&pb->pb_hold)) { - int do_free = 1; - - if (pb->pb_relse) { - atomic_inc(&pb->pb_hold); - if (h) - spin_unlock(&h->pb_hash_lock); - (*(pb->pb_relse)) (pb); - do_free = 0; - } - if (pb->pb_flags & PBF_DELWRI) { - pb->pb_flags |= PBF_ASYNC; - atomic_inc(&pb->pb_hold); - if (h && do_free) - spin_unlock(&h->pb_hash_lock); - pagebuf_delwri_queue(pb, 0); - do_free = 0; - } else if (pb->pb_flags & PBF_FS_MANAGED) { - if (h) - spin_unlock(&h->pb_hash_lock); - do_free = 0; - } - - if (do_free) { - _pagebuf_free_object(h, pb); - } - } else if (h) { - spin_unlock(&h->pb_hash_lock); - } -} - - -/* - * Mutual exclusion on buffers. Locking model: - * - * Buffers associated with inodes for which buffer locking - * is not enabled are not protected by semaphores, and are - * assumed to be exclusively owned by the caller. There is a - * spinlock in the buffer, used by the caller when concurrent - * access is possible. - */ - -/* - * pagebuf_cond_lock - * - * pagebuf_cond_lock locks a buffer object, if it is not already locked. - * Note that this in no way - * locks the underlying pages, so it is only useful for synchronizing - * concurrent use of page buffer objects, not for synchronizing independent - * access to the underlying pages. - */ -int -pagebuf_cond_lock( /* lock buffer, if not locked */ - /* returns -EBUSY if locked) */ - page_buf_t *pb) -{ - int locked; - - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - locked = down_trylock(&pb->pb_sema) == 0; - if (locked) { - PB_SET_OWNER(pb); - } - PB_TRACE(pb, "cond_lock", (long)locked); - return(locked ? 0 : -EBUSY); -} - -/* - * pagebuf_lock_value - * - * Return lock value for a pagebuf - */ -int -pagebuf_lock_value( - page_buf_t *pb) -{ - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - return(atomic_read(&pb->pb_sema.count)); -} - -/* - * pagebuf_lock - * - * pagebuf_lock locks a buffer object. Note that this in no way - * locks the underlying pages, so it is only useful for synchronizing - * concurrent use of page buffer objects, not for synchronizing independent - * access to the underlying pages. - */ -int -pagebuf_lock( - page_buf_t *pb) -{ - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - - PB_TRACE(pb, "lock", 0); - if (atomic_read(&pb->pb_io_remaining)) - blk_run_queues(); - down(&pb->pb_sema); - PB_SET_OWNER(pb); - PB_TRACE(pb, "locked", 0); - return 0; -} - -/* - * pagebuf_unlock - * - * pagebuf_unlock releases the lock on the buffer object created by - * pagebuf_lock or pagebuf_cond_lock (not any - * pinning of underlying pages created by pagebuf_pin). - */ -void -pagebuf_unlock( /* unlock buffer */ - page_buf_t *pb) /* buffer to unlock */ -{ - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - PB_CLEAR_OWNER(pb); - up(&pb->pb_sema); - PB_TRACE(pb, "unlock", 0); -} - - -/* - * Pinning Buffer Storage in Memory - */ - -/* - * pagebuf_pin - * - * pagebuf_pin locks all of the memory represented by a buffer in - * memory. Multiple calls to pagebuf_pin and pagebuf_unpin, for - * the same or different buffers affecting a given page, will - * properly count the number of outstanding "pin" requests. The - * buffer may be released after the pagebuf_pin and a different - * buffer used when calling pagebuf_unpin, if desired. - * pagebuf_pin should be used by the file system when it wants be - * assured that no attempt will be made to force the affected - * memory to disk. It does not assure that a given logical page - * will not be moved to a different physical page. - */ -void -pagebuf_pin( - page_buf_t *pb) -{ - atomic_inc(&pb->pb_pin_count); - PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter); -} - -/* - * pagebuf_unpin - * - * pagebuf_unpin reverses the locking of memory performed by - * pagebuf_pin. Note that both functions affected the logical - * pages associated with the buffer, not the buffer itself. - */ -void -pagebuf_unpin( - page_buf_t *pb) -{ - if (atomic_dec_and_test(&pb->pb_pin_count)) { - wake_up_all(&pb->pb_waiters); - } - PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter); -} - -int -pagebuf_ispin( - page_buf_t *pb) -{ - return atomic_read(&pb->pb_pin_count); -} - -/* - * pagebuf_wait_unpin - * - * pagebuf_wait_unpin waits until all of the memory associated - * with the buffer is not longer locked in memory. It returns - * immediately if none of the affected pages are locked. - */ -static inline void -_pagebuf_wait_unpin( - page_buf_t *pb) -{ - DECLARE_WAITQUEUE (wait, current); - - if (atomic_read(&pb->pb_pin_count) == 0) - return; - - add_wait_queue(&pb->pb_waiters, &wait); - for (;;) { - current->state = TASK_UNINTERRUPTIBLE; - if (atomic_read(&pb->pb_pin_count) == 0) - break; - if (atomic_read(&pb->pb_io_remaining)) - blk_run_queues(); - schedule(); - } - remove_wait_queue(&pb->pb_waiters, &wait); - current->state = TASK_RUNNING; -} - -/* - * Buffer Utility Routines - */ - -/* - * pagebuf_iodone - * - * pagebuf_iodone marks a buffer for which I/O is in progress - * done with respect to that I/O. The pb_iodone routine, if - * present, will be called as a side-effect. - */ -void -pagebuf_iodone_work( - void *v) -{ - page_buf_t *pb = (page_buf_t *)v; - - if (pb->pb_iodone) { - (*(pb->pb_iodone)) (pb); - return; - } - - if (pb->pb_flags & PBF_ASYNC) { - if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse) - pagebuf_unlock(pb); - pagebuf_rele(pb); - } -} - -void -pagebuf_iodone( - page_buf_t *pb, - int dataio, - int schedule) -{ - pb->pb_flags &= ~(PBF_READ | PBF_WRITE); - if (pb->pb_error == 0) { - pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE); - } - - PB_TRACE(pb, "iodone", pb->pb_iodone); - - if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { - if (schedule) { - INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); - queue_work(dataio ? pagebuf_dataio_workqueue : - pagebuf_logio_workqueue, &pb->pb_iodone_work); - } else { - pagebuf_iodone_work(pb); - } - } else { - up(&pb->pb_iodonesema); - } -} - -/* - * pagebuf_ioerror - * - * pagebuf_ioerror sets the error code for a buffer. - */ -void -pagebuf_ioerror( /* mark/clear buffer error flag */ - page_buf_t *pb, /* buffer to mark */ - unsigned int error) /* error to store (0 if none) */ -{ - pb->pb_error = error; - PB_TRACE(pb, "ioerror", (unsigned long)error); -} - -/* - * pagebuf_iostart - * - * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied. - * If necessary, it will arrange for any disk space allocation required, - * and it will break up the request if the block mappings require it. - * The pb_iodone routine in the buffer supplied will only be called - * when all of the subsidiary I/O requests, if any, have been completed. - * pagebuf_iostart calls the pagebuf_ioinitiate routine or - * pagebuf_iorequest, if the former routine is not defined, to start - * the I/O on a given low-level request. - */ -int -pagebuf_iostart( /* start I/O on a buffer */ - page_buf_t *pb, /* buffer to start */ - page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */ - /* PBF_WRITE, PBF_DELWRI, */ - /* PBF_SYNC, PBF_DONT_BLOCK */ -{ - int status = 0; - - PB_TRACE(pb, "iostart", (unsigned long)flags); - - if (flags & PBF_DELWRI) { - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC); - pb->pb_flags |= flags & - (PBF_DELWRI | PBF_ASYNC | PBF_SYNC); - pagebuf_delwri_queue(pb, 1); - return status; - } - - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES); - pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES); - - BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL); - - /* For writes allow an alternate strategy routine to precede - * the actual I/O request (which may not be issued at all in - * a shutdown situation, for example). - */ - status = (flags & PBF_WRITE) ? - pagebuf_iostrategy(pb) : pagebuf_iorequest(pb); - - /* Wait for I/O if we are not an async request. - * Note: async I/O request completion will release the buffer, - * and that can already be done by this point. So using the - * buffer pointer from here on, after async I/O, is invalid. - */ - if (!status && !(flags & PBF_ASYNC)) - status = pagebuf_iowait(pb); - - return status; -} - -/* - * Helper routine for pagebuf_iorequest - */ - -STATIC __inline__ int -_pagebuf_iolocked( - page_buf_t *pb) -{ - ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE)); - if (pb->pb_flags & PBF_READ) - return pb->pb_locked; - return ((pb->pb_flags & _PBF_LOCKABLE) == 0); -} - -STATIC __inline__ void -_pagebuf_iodone( - page_buf_t *pb, - int schedule) -{ - if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { - pb->pb_locked = 0; - pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), schedule); - } -} - -STATIC int -bio_end_io_pagebuf( - struct bio *bio, - unsigned int bytes_done, - int error) -{ - page_buf_t *pb = (page_buf_t *)bio->bi_private; - unsigned int i, blocksize = pb->pb_target->pbr_bsize; - unsigned int sectorshift = pb->pb_target->pbr_sshift; - struct bio_vec *bvec = bio->bi_io_vec; - - if (bio->bi_size) - return 1; - - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - pb->pb_error = EIO; - - for (i = 0; i < bio->bi_vcnt; i++, bvec++) { - struct page *page = bvec->bv_page; - - if (pb->pb_error) { - SetPageError(page); - } else if (blocksize == PAGE_CACHE_SIZE) { - SetPageUptodate(page); - } else if (!PagePrivate(page)) { - unsigned int j, range; - - ASSERT(blocksize < PAGE_CACHE_SIZE); - range = (bvec->bv_offset + bvec->bv_len) >> sectorshift; - for (j = bvec->bv_offset >> sectorshift; j < range; j++) - set_bit(j, &page->private); - if (page->private == (unsigned long)(PAGE_CACHE_SIZE-1)) - SetPageUptodate(page); - } - - if (_pagebuf_iolocked(pb)) { - unlock_page(page); - } - } - - _pagebuf_iodone(pb, 1); - bio_put(bio); - return 0; -} - -void -_pagebuf_ioapply( - page_buf_t *pb) -{ - int i, map_i, total_nr_pages, nr_pages; - struct bio *bio; - int offset = pb->pb_offset; - int size = pb->pb_count_desired; - sector_t sector = pb->pb_bn; - unsigned int blocksize = pb->pb_target->pbr_bsize; - int locking = _pagebuf_iolocked(pb); - - total_nr_pages = pb->pb_page_count; - map_i = 0; - - /* Special code path for reading a sub page size pagebuf in -- - * we populate up the whole page, and hence the other metadata - * in the same page. This optimization is only valid when the - * filesystem block size and the page size are equal. - */ - if ((pb->pb_buffer_length < PAGE_CACHE_SIZE) && - (pb->pb_flags & PBF_READ) && locking && - (blocksize == PAGE_CACHE_SIZE)) { - bio = bio_alloc(GFP_NOIO, 1); - - bio->bi_bdev = pb->pb_target->pbr_bdev; - bio->bi_sector = sector - (offset >> BBSHIFT); - bio->bi_end_io = bio_end_io_pagebuf; - bio->bi_private = pb; - - bio_add_page(bio, pb->pb_pages[0], PAGE_CACHE_SIZE, 0); - size = 0; - - atomic_inc(&pb->pb_io_remaining); - - goto submit_io; - } - - /* Lock down the pages which we need to for the request */ - if (locking && (pb->pb_flags & PBF_WRITE) && (pb->pb_locked == 0)) { - for (i = 0; size; i++) { - int nbytes = PAGE_CACHE_SIZE - offset; - struct page *page = pb->pb_pages[i]; - - if (nbytes > size) - nbytes = size; - - lock_page(page); - - size -= nbytes; - offset = 0; - } - offset = pb->pb_offset; - size = pb->pb_count_desired; - } - -next_chunk: - atomic_inc(&pb->pb_io_remaining); - nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); - if (nr_pages > total_nr_pages) - nr_pages = total_nr_pages; - - bio = bio_alloc(GFP_NOIO, nr_pages); - bio->bi_bdev = pb->pb_target->pbr_bdev; - bio->bi_sector = sector; - bio->bi_end_io = bio_end_io_pagebuf; - bio->bi_private = pb; - - for (; size && nr_pages; nr_pages--, map_i++) { - int nbytes = PAGE_CACHE_SIZE - offset; - - if (nbytes > size) - nbytes = size; - - if (bio_add_page(bio, pb->pb_pages[map_i], - nbytes, offset) < nbytes) - break; - - offset = 0; - sector += nbytes >> BBSHIFT; - size -= nbytes; - total_nr_pages--; - } - -submit_io: - if (likely(bio->bi_size)) { - submit_bio((pb->pb_flags & PBF_READ) ? READ : WRITE, bio); - if (size) - goto next_chunk; - } else { - bio_put(bio); - pagebuf_ioerror(pb, EIO); - } - - if (pb->pb_flags & PBF_RUN_QUEUES) { - pb->pb_flags &= ~PBF_RUN_QUEUES; - if (atomic_read(&pb->pb_io_remaining) > 1) - blk_run_queues(); - } -} - -/* - * pagebuf_iorequest - * - * pagebuf_iorequest is the core I/O request routine. - * It assumes that the buffer is well-formed and - * mapped and ready for physical I/O, unlike - * pagebuf_iostart() and pagebuf_iophysio(). Those - * routines call the pagebuf_ioinitiate routine to start I/O, - * if it is present, or else call pagebuf_iorequest() - * directly if the pagebuf_ioinitiate routine is not present. - * - * This function will be responsible for ensuring access to the - * pages is restricted whilst I/O is in progress - for locking - * pagebufs the pagebuf lock is the mediator, for non-locking - * pagebufs the pages will be locked. In the locking case we - * need to use the pagebuf lock as multiple meta-data buffers - * will reference the same page. - */ -int -pagebuf_iorequest( /* start real I/O */ - page_buf_t *pb) /* buffer to convey to device */ -{ - PB_TRACE(pb, "iorequest", 0); - - if (pb->pb_flags & PBF_DELWRI) { - pagebuf_delwri_queue(pb, 1); - return 0; - } - - if (pb->pb_flags & PBF_WRITE) { - _pagebuf_wait_unpin(pb); - } - - pagebuf_hold(pb); - - /* Set the count to 1 initially, this will stop an I/O - * completion callout which happens before we have started - * all the I/O from calling pagebuf_iodone too early. - */ - atomic_set(&pb->pb_io_remaining, 1); - _pagebuf_ioapply(pb); - _pagebuf_iodone(pb, 0); - - pagebuf_rele(pb); - return 0; -} - -/* - * pagebuf_iowait - * - * pagebuf_iowait waits for I/O to complete on the buffer supplied. - * It returns immediately if no I/O is pending. In any case, it returns - * the error code, if any, or 0 if there is no error. - */ -int -pagebuf_iowait( - page_buf_t *pb) -{ - PB_TRACE(pb, "iowait", 0); - if (atomic_read(&pb->pb_io_remaining)) - blk_run_queues(); - down(&pb->pb_iodonesema); - PB_TRACE(pb, "iowaited", (long)pb->pb_error); - return pb->pb_error; -} - -STATIC void * -pagebuf_mapout_locked( - page_buf_t *pb) -{ - void *old_addr = NULL; - - if (pb->pb_flags & PBF_MAPPED) { - if (pb->pb_flags & _PBF_ADDR_ALLOCATED) - old_addr = pb->pb_addr - pb->pb_offset; - pb->pb_addr = NULL; - pb->pb_flags &= ~(PBF_MAPPED | _PBF_ADDR_ALLOCATED); - } - - return old_addr; /* Caller must free the address space, - * we are under a spin lock, probably - * not safe to do vfree here - */ -} - -caddr_t -pagebuf_offset( - page_buf_t *pb, - size_t offset) -{ - struct page *page; - - offset += pb->pb_offset; - - page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT]; - return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1)); -} - -/* - * pagebuf_iomove - * - * Move data into or out of a buffer. - */ -void -pagebuf_iomove( - page_buf_t *pb, /* buffer to process */ - size_t boff, /* starting buffer offset */ - size_t bsize, /* length to copy */ - caddr_t data, /* data address */ - page_buf_rw_t mode) /* read/write flag */ -{ - size_t bend, cpoff, csize; - struct page *page; - - bend = boff + bsize; - while (boff < bend) { - page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)]; - cpoff = page_buf_poff(boff + pb->pb_offset); - csize = min_t(size_t, - PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff); - - ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); - - switch (mode) { - case PBRW_ZERO: - memset(page_address(page) + cpoff, 0, csize); - break; - case PBRW_READ: - memcpy(data, page_address(page) + cpoff, csize); - break; - case PBRW_WRITE: - memcpy(page_address(page) + cpoff, data, csize); - } - - boff += csize; - data += csize; - } -} - - -/* - * Pagebuf delayed write buffer handling - */ - -STATIC int pbd_active = 1; -STATIC LIST_HEAD(pbd_delwrite_queue); -STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED; - -STATIC void -pagebuf_delwri_queue( - page_buf_t *pb, - int unlock) -{ - PB_TRACE(pb, "delwri_q", (long)unlock); - spin_lock(&pbd_delwrite_lock); - /* If already in the queue, dequeue and place at tail */ - if (!list_empty(&pb->pb_list)) { - if (unlock) { - atomic_dec(&pb->pb_hold); - } - list_del(&pb->pb_list); - } - - list_add_tail(&pb->pb_list, &pbd_delwrite_queue); - pb->pb_flushtime = jiffies + pb_params.age_buffer.val; - spin_unlock(&pbd_delwrite_lock); - - if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) { - pagebuf_unlock(pb); - } -} - -void -pagebuf_delwri_dequeue( - page_buf_t *pb) -{ - PB_TRACE(pb, "delwri_uq", 0); - spin_lock(&pbd_delwrite_lock); - list_del_init(&pb->pb_list); - pb->pb_flags &= ~PBF_DELWRI; - spin_unlock(&pbd_delwrite_lock); -} - -STATIC void -pagebuf_runall_queues( - struct workqueue_struct *queue) -{ - flush_workqueue(queue); -} - -/* Defines for pagebuf daemon */ -DECLARE_WAIT_QUEUE_HEAD(pbd_waitq); -STATIC int force_flush; - -STATIC void -pagebuf_daemon_wakeup( - int flag) -{ - force_flush = flag; - if (waitqueue_active(&pbd_waitq)) { - wake_up_interruptible(&pbd_waitq); - } -} - -typedef void (*timeout_fn)(unsigned long); - -STATIC int -pagebuf_daemon( - void *data) -{ - int count; - page_buf_t *pb; - struct list_head *curr, *next, tmp; - struct timer_list pb_daemon_timer = - TIMER_INITIALIZER((timeout_fn)pagebuf_daemon_wakeup, 0, 0); - - /* Set up the thread */ - daemonize("pagebufd"); - - current->flags |= PF_MEMALLOC; - - INIT_LIST_HEAD(&tmp); - do { - /* swsusp */ - if (current->flags & PF_FREEZE) - refrigerator(PF_IOTHREAD); - - if (pbd_active == 1) { - mod_timer(&pb_daemon_timer, - jiffies + pb_params.flush_interval.val); - interruptible_sleep_on(&pbd_waitq); - } - - if (pbd_active == 0) { - del_timer_sync(&pb_daemon_timer); - } - - spin_lock(&pbd_delwrite_lock); - - count = 0; - list_for_each_safe(curr, next, &pbd_delwrite_queue) { - pb = list_entry(curr, page_buf_t, pb_list); - - PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb)); - - if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) && - (((pb->pb_flags & _PBF_LOCKABLE) == 0) || - !pagebuf_cond_lock(pb))) { - - if (!force_flush && - time_before(jiffies, pb->pb_flushtime)) { - pagebuf_unlock(pb); - break; - } - - pb->pb_flags &= ~PBF_DELWRI; - pb->pb_flags |= PBF_WRITE; - - list_del(&pb->pb_list); - list_add(&pb->pb_list, &tmp); - - count++; - } - } - - spin_unlock(&pbd_delwrite_lock); - while (!list_empty(&tmp)) { - pb = list_entry(tmp.next, page_buf_t, pb_list); - list_del_init(&pb->pb_list); - - pagebuf_iostrategy(pb); - } - - if (as_list_len > 0) - purge_addresses(); - if (count) - blk_run_queues(); - - force_flush = 0; - } while (pbd_active == 1); - - pbd_active = -1; - wake_up_interruptible(&pbd_waitq); - - return 0; -} - -void -pagebuf_delwri_flush( - pb_target_t *target, - u_long flags, - int *pinptr) -{ - page_buf_t *pb; - struct list_head *curr, *next, tmp; - int pincount = 0; - int flush_cnt = 0; - - pagebuf_runall_queues(pagebuf_dataio_workqueue); - pagebuf_runall_queues(pagebuf_logio_workqueue); - - spin_lock(&pbd_delwrite_lock); - INIT_LIST_HEAD(&tmp); - - list_for_each_safe(curr, next, &pbd_delwrite_queue) { - pb = list_entry(curr, page_buf_t, pb_list); - - /* - * Skip other targets, markers and in progress buffers - */ - - if ((pb->pb_flags == 0) || (pb->pb_target != target) || - !(pb->pb_flags & PBF_DELWRI)) { - continue; - } - - PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb)); - if (pagebuf_ispin(pb)) { - pincount++; - continue; - } - - pb->pb_flags &= ~PBF_DELWRI; - pb->pb_flags |= PBF_WRITE; - list_move(&pb->pb_list, &tmp); - } - /* ok found all the items that can be worked on - * drop the lock and process the private list */ - spin_unlock(&pbd_delwrite_lock); - - list_for_each_safe(curr, next, &tmp) { - pb = list_entry(curr, page_buf_t, pb_list); - - if (flags & PBDF_WAIT) - pb->pb_flags &= ~PBF_ASYNC; - else - list_del_init(curr); - - pagebuf_lock(pb); - pagebuf_iostrategy(pb); - if (++flush_cnt > 32) { - blk_run_queues(); - flush_cnt = 0; - } - } - - blk_run_queues(); - - while (!list_empty(&tmp)) { - pb = list_entry(tmp.next, page_buf_t, pb_list); - - list_del_init(&pb->pb_list); - pagebuf_iowait(pb); - if (!pb->pb_relse) - pagebuf_unlock(pb); - pagebuf_rele(pb); - } - - if (pinptr) - *pinptr = pincount; -} - -STATIC int -pagebuf_daemon_start(void) -{ - int rval; - - pagebuf_logio_workqueue = create_workqueue("xfslogd"); - if (!pagebuf_logio_workqueue) - return -ENOMEM; - - pagebuf_dataio_workqueue = create_workqueue("xfsdatad"); - if (!pagebuf_dataio_workqueue) { - destroy_workqueue(pagebuf_logio_workqueue); - return -ENOMEM; - } - - rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); - if (rval < 0) { - destroy_workqueue(pagebuf_logio_workqueue); - destroy_workqueue(pagebuf_dataio_workqueue); - } - - return rval; -} - -/* - * pagebuf_daemon_stop - * - * Note: do not mark as __exit, it is called from pagebuf_terminate. - */ -STATIC void -pagebuf_daemon_stop(void) -{ - pbd_active = 0; - wake_up_interruptible(&pbd_waitq); - wait_event_interruptible(pbd_waitq, pbd_active); - destroy_workqueue(pagebuf_logio_workqueue); - destroy_workqueue(pagebuf_dataio_workqueue); -} - - -/* - * Pagebuf sysctl interface - */ - -STATIC int -pb_stats_clear_handler( - ctl_table *ctl, - int write, - struct file *filp, - void *buffer, - size_t *lenp) -{ - int c, ret; - int *valp = ctl->data; - - ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp); - - if (!ret && write && *valp) { - printk("XFS Clearing pbstats\n"); - for (c = 0; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; - memset(&per_cpu(pbstats, c), 0, - sizeof(struct pbstats)); - } - pb_params.stats_clear.val = 0; - } - - return ret; -} - -STATIC struct ctl_table_header *pagebuf_table_header; - -STATIC ctl_table pagebuf_table[] = { - {PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.flush_interval.min, &pb_params.flush_interval.max}, - - {PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.age_buffer.min, &pb_params.age_buffer.max}, - - {PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val, - sizeof(int), 0644, NULL, &pb_stats_clear_handler, - &sysctl_intvec, NULL, - &pb_params.stats_clear.min, &pb_params.stats_clear.max}, - -#ifdef PAGEBUF_TRACE - {PB_DEBUG, "debug", &pb_params.debug.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.debug.min, &pb_params.debug.max}, -#endif - {0} -}; - -STATIC ctl_table pagebuf_dir_table[] = { - {VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table}, - {0} -}; - -STATIC ctl_table pagebuf_root_table[] = { - {CTL_VM, "vm", NULL, 0, 0555, pagebuf_dir_table}, - {0} -}; - -#ifdef CONFIG_PROC_FS -STATIC int -pagebuf_readstats( - char *buffer, - char **start, - off_t offset, - int count, - int *eof, - void *data) -{ - int c, i, len, val; - - len = 0; - len += sprintf(buffer + len, "pagebuf"); - for (i = 0; i < sizeof(struct pbstats) / sizeof(u_int32_t); i++) { - val = 0; - for (c = 0 ; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; - val += *(((u_int32_t*)&per_cpu(pbstats, c) + i)); - } - len += sprintf(buffer + len, " %u", val); - } - buffer[len++] = '\n'; - - if (offset >= len) { - *start = buffer; - *eof = 1; - return 0; - } - *start = buffer + offset; - if ((len -= offset) > count) - return count; - *eof = 1; - - return len; -} -#endif /* CONFIG_PROC_FS */ - -/* - * Initialization and Termination - */ - -int __init -pagebuf_init(void) -{ - int i; - - pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1); - -#ifdef CONFIG_PROC_FS - if (proc_mkdir("fs/pagebuf", 0)) - create_proc_read_entry( - "fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL); -#endif - - pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (pagebuf_cache == NULL) { - printk("pagebuf: couldn't init pagebuf cache\n"); - pagebuf_terminate(); - return -ENOMEM; - } - - for (i = 0; i < NHASH; i++) { - spin_lock_init(&pbhash[i].pb_hash_lock); - INIT_LIST_HEAD(&pbhash[i].pb_hash); - } - -#ifdef PAGEBUF_TRACE - pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP); -#endif - - pagebuf_daemon_start(); - return 0; -} - - -/* - * pagebuf_terminate. - * - * Note: do not mark as __exit, this is also called from the __init code. - */ -void -pagebuf_terminate(void) -{ - pagebuf_daemon_stop(); - - kmem_cache_destroy(pagebuf_cache); - - unregister_sysctl_table(pagebuf_table_header); -#ifdef CONFIG_PROC_FS - remove_proc_entry("fs/pagebuf/stat", NULL); - remove_proc_entry("fs/pagebuf", NULL); -#endif -} - - -/* - * Module management (for kernel debugger module) - */ -EXPORT_SYMBOL(pagebuf_offset); -#ifdef DEBUG -EXPORT_SYMBOL(pbd_delwrite_queue); -#endif diff -urN linux-2.6.2-rc2/fs/xfs/pagebuf/page_buf.h linux-2.6.2-rc3/fs/xfs/pagebuf/page_buf.h --- linux-2.6.2-rc2/fs/xfs/pagebuf/page_buf.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/pagebuf/page_buf.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -/* - * Written by Steve Lord, Jim Mostek, Russell Cattelan at SGI - */ - -#ifndef __PAGE_BUF_H__ -#define __PAGE_BUF_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Base types - */ - -/* daddr must be signed since -1 is used for bmaps that are not yet allocated */ -typedef loff_t page_buf_daddr_t; - -#define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL)) - -#define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) -#define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -#define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) -#define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) - -typedef enum page_buf_rw_e { - PBRW_READ = 1, /* transfer into target memory */ - PBRW_WRITE = 2, /* transfer from target memory */ - PBRW_ZERO = 3 /* Zero target memory */ -} page_buf_rw_t; - - -typedef enum page_buf_flags_e { /* pb_flags values */ - PBF_READ = (1 << 0), /* buffer intended for reading from device */ - PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ - PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */ - PBF_PARTIAL = (1 << 3), /* buffer partially read */ - PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ - PBF_NONE = (1 << 5), /* buffer not read at all */ - PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ - PBF_FREED = (1 << 7), /* buffer has been freed and is invalid */ - PBF_SYNC = (1 << 8), /* force updates to disk */ - PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ - PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ - PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */ - PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */ - - /* flags used only as arguments to access routines */ - PBF_LOCK = (1 << 13), /* lock requested */ - PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait */ - PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread */ - - /* flags used only internally */ - _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ - _PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads */ - _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ - _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ - _PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated */ - _PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated */ - - PBF_FORCEIO = (1 << 22), /* ignore any cache state */ - PBF_FLUSH = (1 << 23), /* flush disk write cache */ - PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead */ - PBF_RUN_QUEUES = (1 << 25), /* run block device task queue */ - -} page_buf_flags_t; - -#define PBF_UPDATE (PBF_READ | PBF_WRITE) -#define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0) -#define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0) - -typedef struct pb_target { - dev_t pbr_dev; - struct block_device *pbr_bdev; - struct address_space *pbr_mapping; - unsigned int pbr_bsize; - unsigned int pbr_sshift; - size_t pbr_smask; -} pb_target_t; - -/* - * page_buf_t: Buffer structure for page cache-based buffers - * - * This buffer structure is used by the page cache buffer management routines - * to refer to an assembly of pages forming a logical buffer. The actual - * I/O is performed with buffer_head or bio structures, as required by drivers, - * for drivers which do not understand this structure. The buffer structure is - * used on temporary basis only, and discarded when released. - * - * The real data storage is recorded in the page cache. Metadata is - * hashed to the inode for the block device on which the file system resides. - * File data is hashed to the inode for the file. Pages which are only - * partially filled with data have bits set in their block_map entry - * to indicate which disk blocks in the page are not valid. - */ - -struct page_buf_s; -typedef void (*page_buf_iodone_t)(struct page_buf_s *); - /* call-back function on I/O completion */ -typedef void (*page_buf_relse_t)(struct page_buf_s *); - /* call-back function on I/O completion */ -typedef int (*page_buf_bdstrat_t)(struct page_buf_s *); - -#define PB_PAGES 4 - -typedef struct page_buf_s { - struct semaphore pb_sema; /* semaphore for lockables */ - unsigned long pb_flushtime; /* time to flush pagebuf */ - atomic_t pb_pin_count; /* pin count */ - wait_queue_head_t pb_waiters; /* unpin waiters */ - struct list_head pb_list; - page_buf_flags_t pb_flags; /* status flags */ - struct list_head pb_hash_list; - struct pb_target *pb_target; /* logical object */ - atomic_t pb_hold; /* reference count */ - page_buf_daddr_t pb_bn; /* block number for I/O */ - loff_t pb_file_offset; /* offset in file */ - size_t pb_buffer_length; /* size of buffer in bytes */ - size_t pb_count_desired; /* desired transfer size */ - void *pb_addr; /* virtual address of buffer */ - struct work_struct pb_iodone_work; - atomic_t pb_io_remaining;/* #outstanding I/O requests */ - page_buf_iodone_t pb_iodone; /* I/O completion function */ - page_buf_relse_t pb_relse; /* releasing function */ - page_buf_bdstrat_t pb_strat; /* pre-write function */ - struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */ - void *pb_fspriv; - void *pb_fspriv2; - void *pb_fspriv3; - unsigned short pb_error; /* error code on I/O */ - unsigned short pb_page_count; /* size of page array */ - unsigned short pb_offset; /* page offset in first page */ - unsigned char pb_locked; /* page array is locked */ - unsigned char pb_hash_index; /* hash table index */ - struct page **pb_pages; /* array of page pointers */ - struct page *pb_page_array[PB_PAGES]; /* inline pages */ -#ifdef PAGEBUF_LOCK_TRACKING - int pb_last_holder; -#endif -} page_buf_t; - - -/* Finding and Reading Buffers */ - -extern page_buf_t *pagebuf_find( /* find buffer for block if */ - /* the block is in memory */ - struct pb_target *, /* inode for block */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_LOCK */ - -extern page_buf_t *pagebuf_get( /* allocate a buffer */ - struct pb_target *, /* inode for buffer */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ - /* PBF_ASYNC */ - -extern page_buf_t *pagebuf_lookup( - struct pb_target *, - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_READ, PBF_WRITE, */ - /* PBF_FORCEIO, _PBF_LOCKABLE */ - -extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ - /* no memory or disk address */ - size_t len, - struct pb_target *); /* mount point "fake" inode */ - -extern page_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */ - /* without disk address */ - size_t len, - struct pb_target *); /* mount point "fake" inode */ - -extern int pagebuf_associate_memory( - page_buf_t *, - void *, - size_t); - -extern void pagebuf_hold( /* increment reference count */ - page_buf_t *); /* buffer to hold */ - -extern void pagebuf_readahead( /* read ahead into cache */ - struct pb_target *, /* target for buffer (or NULL) */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* additional read flags */ - -/* Releasing Buffers */ - -extern void pagebuf_free( /* deallocate a buffer */ - page_buf_t *); /* buffer to deallocate */ - -extern void pagebuf_rele( /* release hold on a buffer */ - page_buf_t *); /* buffer to release */ - -/* Locking and Unlocking Buffers */ - -extern int pagebuf_cond_lock( /* lock buffer, if not locked */ - /* (returns -EBUSY if locked) */ - page_buf_t *); /* buffer to lock */ - -extern int pagebuf_lock_value( /* return count on lock */ - page_buf_t *); /* buffer to check */ - -extern int pagebuf_lock( /* lock buffer */ - page_buf_t *); /* buffer to lock */ - -extern void pagebuf_unlock( /* unlock buffer */ - page_buf_t *); /* buffer to unlock */ - -/* Buffer Read and Write Routines */ - -extern void pagebuf_iodone( /* mark buffer I/O complete */ - page_buf_t *, /* buffer to mark */ - int, /* use data/log helper thread. */ - int); /* run completion locally, or in - * a helper thread. */ - -extern void pagebuf_ioerror( /* mark buffer in error (or not) */ - page_buf_t *, /* buffer to mark */ - unsigned int); /* error to store (0 if none) */ - -extern int pagebuf_iostart( /* start I/O on a buffer */ - page_buf_t *, /* buffer to start */ - page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ - /* PBF_READ, PBF_WRITE, */ - /* PBF_DELWRI, PBF_SYNC */ - -extern int pagebuf_iorequest( /* start real I/O */ - page_buf_t *); /* buffer to convey to device */ - -extern int pagebuf_iowait( /* wait for buffer I/O done */ - page_buf_t *); /* buffer to wait on */ - -extern void pagebuf_iomove( /* move data in/out of pagebuf */ - page_buf_t *, /* buffer to manipulate */ - size_t, /* starting buffer offset */ - size_t, /* length in buffer */ - caddr_t, /* data pointer */ - page_buf_rw_t); /* direction */ - -static inline int pagebuf_iostrategy(page_buf_t *pb) -{ - return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb); -} - -static inline int pagebuf_geterror(page_buf_t *pb) -{ - return pb ? pb->pb_error : ENOMEM; -} - -/* Buffer Utility Routines */ - -extern caddr_t pagebuf_offset( /* pointer at offset in buffer */ - page_buf_t *, /* buffer to offset into */ - size_t); /* offset */ - -/* Pinning Buffer Storage in Memory */ - -extern void pagebuf_pin( /* pin buffer in memory */ - page_buf_t *); /* buffer to pin */ - -extern void pagebuf_unpin( /* unpin buffered data */ - page_buf_t *); /* buffer to unpin */ - -extern int pagebuf_ispin( /* check if buffer is pinned */ - page_buf_t *); /* buffer to check */ - -/* Delayed Write Buffer Routines */ - -#define PBDF_WAIT 0x01 -extern void pagebuf_delwri_flush( - pb_target_t *, - unsigned long, - int *); - -extern void pagebuf_delwri_dequeue( - page_buf_t *); - -/* Buffer Daemon Setup Routines */ - -extern int pagebuf_init(void); -extern void pagebuf_terminate(void); - - -#ifdef PAGEBUF_TRACE -extern ktrace_t *pagebuf_trace_buf; -extern void pagebuf_trace( - page_buf_t *, /* buffer being traced */ - char *, /* description of operation */ - void *, /* arbitrary diagnostic value */ - void *); /* return address */ -#else -# define pagebuf_trace(pb, id, ptr, ra) do { } while (0) -#endif - -#define pagebuf_target_name(target) \ - ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; }) - -#endif /* __PAGE_BUF_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/quota/xfs_qm.c linux-2.6.2-rc3/fs/xfs/quota/xfs_qm.c --- linux-2.6.2-rc2/fs/xfs/quota/xfs_qm.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/quota/xfs_qm.c 2004-01-30 18:49:23.000000000 -0800 @@ -78,7 +78,6 @@ */ mutex_t xfs_Gqm_lock; struct xfs_qm *xfs_Gqm; -EXPORT_SYMBOL(xfs_Gqm); /* used by xfsidbg */ kmem_zone_t *qm_dqzone; kmem_zone_t *qm_dqtrxzone; diff -urN linux-2.6.2-rc2/fs/xfs/support/kmem.h linux-2.6.2-rc3/fs/xfs/support/kmem.h --- linux-2.6.2-rc2/fs/xfs/support/kmem.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/kmem.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_KMEM_H__ -#define __XFS_SUPPORT_KMEM_H__ - -#include -#include -#include -#include - -/* - * Cutoff point to use vmalloc instead of kmalloc. - */ -#define MAX_SLAB_SIZE 0x10000 - -/* - * XFS uses slightly different names for these due to the - * IRIX heritage. - */ -#define kmem_zone kmem_cache_s -#define kmem_zone_t kmem_cache_t - -#define KM_SLEEP 0x0001 -#define KM_NOSLEEP 0x0002 -#define KM_NOFS 0x0004 - -typedef unsigned long xfs_pflags_t; - -#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) - -#define PFLAGS_SET_FSTRANS(STATEP) do { \ - *(STATEP) = current->flags; \ - current->flags |= PF_FSTRANS; \ -} while (0) - -#define PFLAGS_RESTORE(STATEP) do { \ - current->flags = *(STATEP); \ -} while (0) - -#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \ - *(NSTATEP) = *(OSTATEP); \ -} while (0) - -/* - * XXX get rid of the unconditional __GFP_NOFAIL by adding - * a KM_FAIL flag and using it where we're allowed to fail. - */ -static __inline unsigned int -kmem_flags_convert(int flags) -{ - int lflags; - -#if DEBUG - if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) { - printk(KERN_WARNING - "XFS: memory allocation with wrong flags (%x)\n", flags); - BUG(); - } -#endif - - lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL); - - /* avoid recusive callbacks to filesystem during transactions */ - if (PFLAGS_TEST_FSTRANS()) - lflags &= ~__GFP_FS; - - return lflags; -} - -static __inline void * -kmem_alloc(size_t size, int flags) -{ - if (unlikely(MAX_SLAB_SIZE < size)) - /* Avoid doing filesystem sensitive stuff to get this */ - return __vmalloc(size, kmem_flags_convert(flags), PAGE_KERNEL); - return kmalloc(size, kmem_flags_convert(flags)); -} - -static __inline void * -kmem_zalloc(size_t size, int flags) -{ - void *ptr = kmem_alloc(size, flags); - if (likely(ptr != NULL)) - memset(ptr, 0, size); - return ptr; -} - -static __inline void -kmem_free(void *ptr, size_t size) -{ - if (unlikely((unsigned long)ptr < VMALLOC_START || - (unsigned long)ptr >= VMALLOC_END)) - kfree(ptr); - else - vfree(ptr); -} - -static __inline void * -kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags) -{ - void *new = kmem_alloc(newsize, flags); - - if (likely(ptr != NULL)) { - if (likely(new != NULL)) - memcpy(new, ptr, min(oldsize, newsize)); - kmem_free(ptr, oldsize); - } - - return new; -} - -static __inline kmem_zone_t * -kmem_zone_init(int size, char *zone_name) -{ - return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL); -} - -static __inline void * -kmem_zone_alloc(kmem_zone_t *zone, int flags) -{ - return kmem_cache_alloc(zone, kmem_flags_convert(flags)); -} - -static __inline void * -kmem_zone_zalloc(kmem_zone_t *zone, int flags) -{ - void *ptr = kmem_zone_alloc(zone, flags); - if (likely(ptr != NULL)) - memset(ptr, 0, kmem_cache_size(zone)); - return ptr; -} - -static __inline void -kmem_zone_free(kmem_zone_t *zone, void *ptr) -{ - kmem_cache_free(zone, ptr); -} - -typedef struct shrinker *kmem_shaker_t; -typedef int (*kmem_shake_func_t)(int, unsigned int); - -static __inline kmem_shaker_t -kmem_shake_register(kmem_shake_func_t sfunc) -{ - return set_shrinker(DEFAULT_SEEKS, sfunc); -} - -static __inline void -kmem_shake_deregister(kmem_shaker_t shrinker) -{ - remove_shrinker(shrinker); -} - -static __inline int -kmem_shake_allow(unsigned int gfp_mask) -{ - return (gfp_mask & __GFP_WAIT); -} - -#endif /* __XFS_SUPPORT_KMEM_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/ktrace.c linux-2.6.2-rc3/fs/xfs/support/ktrace.c --- linux-2.6.2-rc2/fs/xfs/support/ktrace.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/ktrace.c 2004-01-30 18:49:23.000000000 -0800 @@ -30,13 +30,12 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#include #include #include #include -#include "kmem.h" -#include "spin.h" +#include +#include #include "debug.h" #include "ktrace.h" @@ -273,7 +272,6 @@ } return ktep; } -EXPORT_SYMBOL(ktrace_first); /* * ktrace_next() @@ -308,7 +306,6 @@ return ktep; } -EXPORT_SYMBOL(ktrace_next); /* * ktrace_skip() diff -urN linux-2.6.2-rc2/fs/xfs/support/ktrace.h linux-2.6.2-rc3/fs/xfs/support/ktrace.h --- linux-2.6.2-rc2/fs/xfs/support/ktrace.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/ktrace.h 2004-01-30 18:49:23.000000000 -0800 @@ -32,7 +32,7 @@ #ifndef __XFS_SUPPORT_KTRACE_H__ #define __XFS_SUPPORT_KTRACE_H__ -#include +#include /* * Trace buffer entry structure. diff -urN linux-2.6.2-rc2/fs/xfs/support/mrlock.c linux-2.6.2-rc3/fs/xfs/support/mrlock.c --- linux-2.6.2-rc2/fs/xfs/support/mrlock.c 2004-01-08 22:59:06.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/mrlock.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#include -#include -#include -#include -#include - -#include "mrlock.h" - - -#if USE_RW_WAIT_QUEUE_SPINLOCK -# define wq_write_lock write_lock -#else -# define wq_write_lock spin_lock -#endif - -/* - * We don't seem to need lock_type (only one supported), name, or - * sequence. But, XFS will pass it so let's leave them here for now. - */ -/* ARGSUSED */ -void -mrlock_init(mrlock_t *mrp, int lock_type, char *name, long sequence) -{ - mrp->mr_count = 0; - mrp->mr_reads_waiting = 0; - mrp->mr_writes_waiting = 0; - init_waitqueue_head(&mrp->mr_readerq); - init_waitqueue_head(&mrp->mr_writerq); - mrp->mr_lock = SPIN_LOCK_UNLOCKED; -} - -/* - * Macros to lock/unlock the mrlock_t. - */ - -#define MRLOCK(m) spin_lock(&(m)->mr_lock); -#define MRUNLOCK(m) spin_unlock(&(m)->mr_lock); - - -/* - * lock_wait should never be called in an interrupt thread. - * - * mrlocks can sleep (i.e. call schedule) and so they can't ever - * be called from an interrupt thread. - * - * threads that wake-up should also never be invoked from interrupt threads. - * - * But, waitqueue_lock is locked from interrupt threads - and we are - * called with interrupts disabled, so it is all OK. - */ - -/* ARGSUSED */ -void -lock_wait(wait_queue_head_t *q, spinlock_t *lock, int rw) -{ - DECLARE_WAITQUEUE( wait, current ); - - __set_current_state(TASK_UNINTERRUPTIBLE); - - spin_lock(&q->lock); - if (rw) { - __add_wait_queue_tail(q, &wait); - } else { - __add_wait_queue(q, &wait); - } - - spin_unlock(&q->lock); - spin_unlock(lock); - - schedule(); - - spin_lock(&q->lock); - __remove_wait_queue(q, &wait); - spin_unlock(&q->lock); - - spin_lock(lock); - - /* return with lock held */ -} - -/* ARGSUSED */ -void -mrfree(mrlock_t *mrp) -{ -} - -/* ARGSUSED */ -void -mrlock(mrlock_t *mrp, int type, int flags) -{ - if (type == MR_ACCESS) - mraccess(mrp); - else - mrupdate(mrp); -} - -/* ARGSUSED */ -void -mraccessf(mrlock_t *mrp, int flags) -{ - MRLOCK(mrp); - if(mrp->mr_writes_waiting > 0) { - mrp->mr_reads_waiting++; - lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); - mrp->mr_reads_waiting--; - } - while (mrp->mr_count < 0) { - mrp->mr_reads_waiting++; - lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); - mrp->mr_reads_waiting--; - } - mrp->mr_count++; - MRUNLOCK(mrp); -} - -/* ARGSUSED */ -void -mrupdatef(mrlock_t *mrp, int flags) -{ - MRLOCK(mrp); - while(mrp->mr_count) { - mrp->mr_writes_waiting++; - lock_wait(&mrp->mr_writerq, &mrp->mr_lock, 1); - mrp->mr_writes_waiting--; - } - - mrp->mr_count = -1; /* writer on it */ - MRUNLOCK(mrp); -} - -int -mrtryaccess(mrlock_t *mrp) -{ - MRLOCK(mrp); - /* - * If anyone is waiting for update access or the lock is held for update - * fail the request. - */ - if(mrp->mr_writes_waiting > 0 || mrp->mr_count < 0) { - MRUNLOCK(mrp); - return 0; - } - mrp->mr_count++; - MRUNLOCK(mrp); - return 1; -} - -int -mrtrypromote(mrlock_t *mrp) -{ - MRLOCK(mrp); - - if(mrp->mr_count == 1) { /* We are the only thread with the lock */ - mrp->mr_count = -1; /* writer on it */ - MRUNLOCK(mrp); - return 1; - } - - MRUNLOCK(mrp); - return 0; -} - -int -mrtryupdate(mrlock_t *mrp) -{ - MRLOCK(mrp); - - if(mrp->mr_count) { - MRUNLOCK(mrp); - return 0; - } - - mrp->mr_count = -1; /* writer on it */ - MRUNLOCK(mrp); - return 1; -} - -static __inline__ void mrwake(mrlock_t *mrp) -{ - /* - * First, if the count is now 0, we need to wake-up anyone waiting. - */ - if (!mrp->mr_count) { - if (mrp->mr_writes_waiting) { /* Wake-up first writer waiting */ - wake_up(&mrp->mr_writerq); - } else if (mrp->mr_reads_waiting) { /* Wakeup any readers waiting */ - wake_up(&mrp->mr_readerq); - } - } -} - -void -mraccunlock(mrlock_t *mrp) -{ - MRLOCK(mrp); - mrp->mr_count--; - mrwake(mrp); - MRUNLOCK(mrp); -} - -void -mrunlock(mrlock_t *mrp) -{ - MRLOCK(mrp); - if (mrp->mr_count < 0) { - mrp->mr_count = 0; - } else { - mrp->mr_count--; - } - mrwake(mrp); - MRUNLOCK(mrp); -} - -int -ismrlocked(mrlock_t *mrp, int type) /* No need to lock since info can change */ -{ - if (type == MR_ACCESS) - return (mrp->mr_count > 0); /* Read lock */ - else if (type == MR_UPDATE) - return (mrp->mr_count < 0); /* Write lock */ - else if (type == (MR_UPDATE | MR_ACCESS)) - return (mrp->mr_count); /* Any type of lock held */ - else /* Any waiters */ - return (mrp->mr_reads_waiting | mrp->mr_writes_waiting); -} - -/* - * Demote from update to access. We better be the only thread with the - * lock in update mode so it should be easy to set to 1. - * Wake-up any readers waiting. - */ - -void -mrdemote(mrlock_t *mrp) -{ - MRLOCK(mrp); - mrp->mr_count = 1; - if (mrp->mr_reads_waiting) { /* Wakeup all readers waiting */ - wake_up(&mrp->mr_readerq); - } - MRUNLOCK(mrp); -} diff -urN linux-2.6.2-rc2/fs/xfs/support/mrlock.h linux-2.6.2-rc3/fs/xfs/support/mrlock.h --- linux-2.6.2-rc2/fs/xfs/support/mrlock.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/mrlock.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_MRLOCK_H__ -#define __XFS_SUPPORT_MRLOCK_H__ - -#include -#include -#include -#include - -/* - * Implement mrlocks on Linux that work for XFS. - * - * These are sleep locks and not spinlocks. If one wants read/write spinlocks, - * use read_lock, write_lock, ... see spinlock.h. - */ - -typedef struct mrlock_s { - int mr_count; - unsigned short mr_reads_waiting; - unsigned short mr_writes_waiting; - wait_queue_head_t mr_readerq; - wait_queue_head_t mr_writerq; - spinlock_t mr_lock; -} mrlock_t; - -#define MR_ACCESS 1 -#define MR_UPDATE 2 - -#define MRLOCK_BARRIER 0x1 -#define MRLOCK_ALLOW_EQUAL_PRI 0x8 - -/* - * mraccessf/mrupdatef take flags to be passed in while sleeping; - * only PLTWAIT is currently supported. - */ - -extern void mraccessf(mrlock_t *, int); -extern void mrupdatef(mrlock_t *, int); -extern void mrlock(mrlock_t *, int, int); -extern void mrunlock(mrlock_t *); -extern void mraccunlock(mrlock_t *); -extern int mrtryupdate(mrlock_t *); -extern int mrtryaccess(mrlock_t *); -extern int mrtrypromote(mrlock_t *); -extern void mrdemote(mrlock_t *); - -extern int ismrlocked(mrlock_t *, int); -extern void mrlock_init(mrlock_t *, int type, char *name, long sequence); -extern void mrfree(mrlock_t *); - -#define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1) -#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */ -#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */ -#define mrislocked_access(mrp) ((mrp)->mr_count > 0) -#define mrislocked_update(mrp) ((mrp)->mr_count < 0) - -#endif /* __XFS_SUPPORT_MRLOCK_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/mutex.h linux-2.6.2-rc3/fs/xfs/support/mutex.h --- linux-2.6.2-rc2/fs/xfs/support/mutex.h 2004-01-08 22:59:03.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/mutex.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_MUTEX_H__ -#define __XFS_SUPPORT_MUTEX_H__ - -#include -#include - -/* - * Map the mutex'es from IRIX to Linux semaphores. - * - * Destroy just simply initializes to -99 which should block all other - * callers. - */ -#define MUTEX_DEFAULT 0x0 -typedef struct semaphore mutex_t; - -#define mutex_init(lock, type, name) sema_init(lock, 1) -#define mutex_destroy(lock) sema_init(lock, -99) -#define mutex_lock(lock, num) down(lock) -#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) -#define mutex_unlock(lock) up(lock) - -#endif /* __XFS_SUPPORT_MUTEX_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/sema.h linux-2.6.2-rc3/fs/xfs/support/sema.h --- linux-2.6.2-rc2/fs/xfs/support/sema.h 2004-01-08 23:00:13.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/sema.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SEMA_H__ -#define __XFS_SUPPORT_SEMA_H__ - -#include -#include -#include -#include - -/* - * sema_t structure just maps to struct semaphore in Linux kernel. - */ - -typedef struct semaphore sema_t; - -#define init_sema(sp, val, c, d) sema_init(sp, val) -#define initsema(sp, val) sema_init(sp, val) -#define initnsema(sp, val, name) sema_init(sp, val) -#define psema(sp, b) down(sp) -#define vsema(sp) up(sp) -#define valusema(sp) (atomic_read(&(sp)->count)) -#define freesema(sema) - -/* - * Map cpsema (try to get the sema) to down_trylock. We need to switch - * the return values since cpsema returns 1 (acquired) 0 (failed) and - * down_trylock returns the reverse 0 (acquired) 1 (failed). - */ - -#define cpsema(sp) (down_trylock(sp) ? 0 : 1) - -/* - * Didn't do cvsema(sp). Not sure how to map this to up/down/... - * It does a vsema if the values is < 0 other wise nothing. - */ - -#endif /* __XFS_SUPPORT_SEMA_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/spin.h linux-2.6.2-rc3/fs/xfs/support/spin.h --- linux-2.6.2-rc2/fs/xfs/support/spin.h 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/spin.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SPIN_H__ -#define __XFS_SUPPORT_SPIN_H__ - -#include /* preempt needs this */ -#include - -/* - * Map lock_t from IRIX to Linux spinlocks. - * - * Note that linux turns on/off spinlocks depending on CONFIG_SMP. - * We don't need to worry about SMP or not here. - */ - -#define SPLDECL(s) unsigned long s - -typedef spinlock_t lock_t; - -#define spinlock_init(lock, name) spin_lock_init(lock) -#define spinlock_destroy(lock) - -static inline unsigned long mutex_spinlock(lock_t *lock) -{ - spin_lock(lock); - return 0; -} - -/*ARGSUSED*/ -static inline void mutex_spinunlock(lock_t *lock, unsigned long s) -{ - spin_unlock(lock); -} - -static inline void nested_spinlock(lock_t *lock) -{ - spin_lock(lock); -} - -static inline void nested_spinunlock(lock_t *lock) -{ - spin_unlock(lock); -} - -#endif /* __XFS_SUPPORT_SPIN_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/sv.h linux-2.6.2-rc3/fs/xfs/support/sv.h --- linux-2.6.2-rc2/fs/xfs/support/sv.h 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/sv.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SV_H__ -#define __XFS_SUPPORT_SV_H__ - -#include -#include -#include - -/* - * Synchronisation variables. - * - * (Parameters "pri", "svf" and "rts" are not implemented) - */ - -typedef struct sv_s { - wait_queue_head_t waiters; -} sv_t; - -#define SV_FIFO 0x0 /* sv_t is FIFO type */ -#define SV_LIFO 0x2 /* sv_t is LIFO type */ -#define SV_PRIO 0x4 /* sv_t is PRIO type */ -#define SV_KEYED 0x6 /* sv_t is KEYED type */ -#define SV_DEFAULT SV_FIFO - - -static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state, - unsigned long timeout) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue_exclusive(&sv->waiters, &wait); - __set_current_state(state); - spin_unlock(lock); - - schedule_timeout(timeout); - - remove_wait_queue(&sv->waiters, &wait); -} - -#define init_sv(sv,type,name,flag) \ - init_waitqueue_head(&(sv)->waiters) -#define sv_init(sv,flag,name) \ - init_waitqueue_head(&(sv)->waiters) -#define sv_destroy(sv) \ - /*NOTHING*/ -#define sv_wait(sv, pri, lock, s) \ - _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) -#define sv_wait_sig(sv, pri, lock, s) \ - _sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) -#define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \ - _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts)) -#define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \ - _sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts)) -#define sv_signal(sv) \ - wake_up(&(sv)->waiters) -#define sv_broadcast(sv) \ - wake_up_all(&(sv)->waiters) - -#endif /* __XFS_SUPPORT_SV_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/time.h linux-2.6.2-rc3/fs/xfs/support/time.h --- linux-2.6.2-rc2/fs/xfs/support/time.h 2004-01-08 23:00:12.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/time.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_TIME_H__ -#define __XFS_SUPPORT_TIME_H__ - -#include -#include - -typedef struct timespec timespec_t; - -static inline void delay(long ticks) -{ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(ticks); -} - -static inline void nanotime(struct timespec *tvp) -{ - *tvp = CURRENT_TIME; -} - -#endif /* __XFS_SUPPORT_TIME_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/support/uuid.c linux-2.6.2-rc3/fs/xfs/support/uuid.c --- linux-2.6.2-rc2/fs/xfs/support/uuid.c 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/support/uuid.c 2004-01-30 18:49:23.000000000 -0800 @@ -30,14 +30,7 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#include -#include -#include -#include "time.h" -#include "uuid.h" -#include "kmem.h" -#include "debug.h" -#include "mutex.h" +#include static mutex_t uuid_monitor; static int uuid_table_size; diff -urN linux-2.6.2-rc2/fs/xfs/xfs.h linux-2.6.2-rc3/fs/xfs/xfs.h --- linux-2.6.2-rc2/fs/xfs/xfs.h 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs.h 2004-01-30 18:49:23.000000000 -0800 @@ -32,28 +32,8 @@ #ifndef __XFS_H__ #define __XFS_H__ -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include -#include #endif /* __XFS_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/xfs_attr.c linux-2.6.2-rc3/fs/xfs/xfs_attr.c --- linux-2.6.2-rc2/fs/xfs/xfs_attr.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_attr.c 2004-01-30 18:49:23.000000000 -0800 @@ -106,12 +106,11 @@ #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ #define ATTR_RMTVALUE_TRANSBLKS 8 /* max # of blks in a transaction */ -#if defined(DEBUG) +#if defined(XFS_ATTR_TRACE) ktrace_t *xfs_attr_trace_buf; #endif - /*======================================================================== * Overall external interface routines. *========================================================================*/ @@ -2589,6 +2588,14 @@ } STATIC int +attr_secure_capable( + struct vnode *vp, + cred_t *cred) +{ + return -ENOSECURITY; +} + +STATIC int attr_system_set( struct vnode *vp, char *name, void *data, size_t size, int xflags) { @@ -2651,6 +2658,16 @@ .attr_capable = attr_trusted_capable, }; +struct attrnames attr_secure = { + .attr_name = "security.", + .attr_namelen = sizeof("security.") - 1, + .attr_flag = ATTR_SECURE, + .attr_get = attr_generic_get, + .attr_set = attr_generic_set, + .attr_remove = attr_generic_remove, + .attr_capable = attr_secure_capable, +}; + struct attrnames attr_user = { .attr_name = "user.", .attr_namelen = sizeof("user.") - 1, @@ -2661,4 +2678,4 @@ }; struct attrnames *attr_namespaces[] = - { &attr_system, &attr_trusted, &attr_user }; + { &attr_system, &attr_trusted, &attr_secure, &attr_user }; diff -urN linux-2.6.2-rc2/fs/xfs/xfs_attr.h linux-2.6.2-rc3/fs/xfs/xfs_attr.h --- linux-2.6.2-rc2/fs/xfs/xfs_attr.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_attr.h 2004-01-30 18:49:23.000000000 -0800 @@ -69,8 +69,9 @@ attrcapable_t attr_capable; } attrnames_t; -#define ATTR_NAMECOUNT 3 +#define ATTR_NAMECOUNT 4 extern struct attrnames attr_user; +extern struct attrnames attr_secure; extern struct attrnames attr_system; extern struct attrnames attr_trusted; extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; @@ -86,6 +87,7 @@ #define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ #define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ #define ATTR_TRUST 0x0004 /* -- unused, from IRIX -- */ +#define ATTR_SECURE 0x0008 /* use attrs in security namespace */ #define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ #define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */ #define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */ diff -urN linux-2.6.2-rc2/fs/xfs/xfs_attr_leaf.c linux-2.6.2-rc3/fs/xfs/xfs_attr_leaf.c --- linux-2.6.2-rc2/fs/xfs/xfs_attr_leaf.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_attr_leaf.c 2004-01-30 18:49:23.000000000 -0800 @@ -159,6 +159,9 @@ continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -173,7 +176,8 @@ sfe->namelen = args->namelen; INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen); - sfe->flags = (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; + sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : + ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); memcpy(sfe->nameval, args->name, args->namelen); memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); INT_MOD(sf->hdr.count, ARCH_CONVERT, 1); @@ -209,6 +213,9 @@ continue; if (memcmp(sfe->nameval, args->name, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -253,6 +260,9 @@ continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -281,6 +291,9 @@ continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -369,7 +382,8 @@ nargs.valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); nargs.hashval = xfs_da_hashname((char *)sfe->nameval, sfe->namelen); - nargs.flags = (sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; + nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : + ((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ ASSERT(error == ENOATTR); error = xfs_attr_leaf_add(bp, &nargs); @@ -446,14 +460,15 @@ i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { attrnames_t *namesp; - namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : - &attr_user; if (((context->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0) && !(context->flags & ATTR_KERNFULLS)) { sfe = XFS_ATTR_SF_NEXTENTRY(sfe); continue; } + namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure: + ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : + &attr_user); if (context->flags & ATTR_KERNOVAL) { ASSERT(context->flags & ATTR_KERNAMELS); context->count += namesp->attr_namelen + @@ -548,8 +563,9 @@ for ( ; i < nsbuf; i++, sbp++) { attrnames_t *namesp; - namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : - &attr_user; + namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure : + ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : + &attr_user); if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) { cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT); @@ -668,7 +684,8 @@ nargs.value = (char *)&name_loc->nameval[nargs.namelen]; nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT); nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); - nargs.flags = (entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; + nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : + ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); xfs_attr_shortform_add(&nargs); } error = 0; @@ -963,7 +980,8 @@ + INT_GET(map->size, ARCH_CONVERT)); INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); entry->flags = tmp ? XFS_ATTR_LOCAL : 0; - entry->flags |= (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; + entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : + ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); if (args->rename) { entry->flags |= XFS_ATTR_INCOMPLETE; if ((args->blkno2 == args->blkno) && @@ -1881,6 +1899,9 @@ if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((entry->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -1893,6 +1914,9 @@ if (memcmp(args->name, (char *)name_rmt->name, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((entry->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -2290,8 +2314,9 @@ !(context->flags & ATTR_KERNFULLS)) continue; /* skip non-matching entries */ - namesp = (entry->flags & XFS_ATTR_ROOT) ? &attr_trusted : - &attr_user; + namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure : + ((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted : + &attr_user); if (entry->flags & XFS_ATTR_LOCAL) { name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); diff -urN linux-2.6.2-rc2/fs/xfs/xfs_attr_leaf.h linux-2.6.2-rc3/fs/xfs/xfs_attr_leaf.h --- linux-2.6.2-rc2/fs/xfs/xfs_attr_leaf.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_attr_leaf.h 2004-01-30 18:49:23.000000000 -0800 @@ -73,9 +73,9 @@ * to work "forw"ard. If none matches, continue with the "forw"ard leaf * nodes until the hash key changes or the attribute name is found. * - * We store the fact that an attribute is a ROOT versus USER attribute in + * We store the fact that an attribute is a ROOT/USER/SECURE attribute in * the leaf_entry. The namespaces are independent only because we also look - * at the root/user bit when we are looking for a matching attribute name. + * at the namespace bit when we are looking for a matching attribute name. * * We also store a "incomplete" bit in the leaf_entry. It shows that an * attribute is in the middle of being created and should not be shown to @@ -102,7 +102,7 @@ struct xfs_attr_leaf_entry { /* sorted on key, not name */ xfs_dahash_t hashval; /* hash value of name */ __uint16_t nameidx; /* index into buffer of name/value */ - __uint8_t flags; /* LOCAL, ROOT and INCOMPLETE flags */ + __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ __uint8_t pad2; /* unused pad byte */ } entries[1]; /* variable sized array */ struct xfs_attr_leaf_name_local { @@ -130,9 +130,11 @@ */ #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ +#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) +#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) /* diff -urN linux-2.6.2-rc2/fs/xfs/xfs_behavior.c linux-2.6.2-rc3/fs/xfs/xfs_behavior.c --- linux-2.6.2-rc2/fs/xfs/xfs_behavior.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_behavior.c 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + * + */ +#include "xfs.h" + +/* + * Source file used to associate/disassociate behaviors with virtualized + * objects. See xfs_behavior.h for more information about behaviors, etc. + * + * The implementation is split between functions in this file and macros + * in xfs_behavior.h. + */ + +/* + * Insert a new behavior descriptor into a behavior chain. + * + * The behavior chain is ordered based on the 'position' number which + * lives in the first field of the ops vector (higher numbers first). + * + * Attemps to insert duplicate ops result in an EINVAL return code. + * Otherwise, return 0 to indicate success. + */ +int +bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) +{ + bhv_desc_t *curdesc, *prev; + int position; + + /* + * Validate the position value of the new behavior. + */ + position = BHV_POSITION(bdp); + ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); + + /* + * Find location to insert behavior. Check for duplicates. + */ + prev = NULL; + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + /* Check for duplication. */ + if (curdesc->bd_ops == bdp->bd_ops) { + ASSERT(0); + return EINVAL; + } + + /* Find correct position */ + if (position >= BHV_POSITION(curdesc)) { + ASSERT(position != BHV_POSITION(curdesc)); + break; /* found it */ + } + + prev = curdesc; + } + + if (prev == NULL) { + /* insert at front of chain */ + bdp->bd_next = bhp->bh_first; + bhp->bh_first = bdp; + } else { + /* insert after prev */ + bdp->bd_next = prev->bd_next; + prev->bd_next = bdp; + } + + return 0; +} + +/* + * Remove a behavior descriptor from a position in a behavior chain; + * the postition is guaranteed not to be the first position. + * Should only be called by the bhv_remove() macro. + */ +void +bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) +{ + bhv_desc_t *curdesc, *prev; + + ASSERT(bhp->bh_first != NULL); + ASSERT(bhp->bh_first->bd_next != NULL); + + prev = bhp->bh_first; + for (curdesc = bhp->bh_first->bd_next; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + if (curdesc == bdp) + break; /* found it */ + prev = curdesc; + } + + ASSERT(curdesc == bdp); + prev->bd_next = bdp->bd_next; /* remove from after prev */ +} + +/* + * Look for a specific ops vector on the specified behavior chain. + * Return the associated behavior descriptor. Or NULL, if not found. + */ +bhv_desc_t * +bhv_lookup(bhv_head_t *bhp, void *ops) +{ + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + if (curdesc->bd_ops == ops) + return curdesc; + } + + return NULL; +} + +/* + * Looks for the first behavior within a specified range of positions. + * Return the associated behavior descriptor. Or NULL, if none found. + */ +bhv_desc_t * +bhv_lookup_range(bhv_head_t *bhp, int low, int high) +{ + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + int position = BHV_POSITION(curdesc); + + if (position <= high) { + if (position >= low) + return curdesc; + return NULL; + } + } + + return NULL; +} + +/* + * Return the base behavior in the chain, or NULL if the chain + * is empty. + * + * The caller has not read locked the behavior chain, so acquire the + * lock before traversing the chain. + */ +bhv_desc_t * +bhv_base(bhv_head_t *bhp) +{ + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + if (curdesc->bd_next == NULL) { + return curdesc; + } + } + + return NULL; +} + +void +bhv_head_init( + bhv_head_t *bhp, + char *name) +{ + bhp->bh_first = NULL; +} + +void +bhv_insert_initial( + bhv_head_t *bhp, + bhv_desc_t *bdp) +{ + ASSERT(bhp->bh_first == NULL); + (bhp)->bh_first = bdp; +} + +void +bhv_head_destroy( + bhv_head_t *bhp) +{ + ASSERT(bhp->bh_first == NULL); +} diff -urN linux-2.6.2-rc2/fs/xfs/xfs_behavior.h linux-2.6.2-rc3/fs/xfs/xfs_behavior.h --- linux-2.6.2-rc2/fs/xfs/xfs_behavior.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_behavior.h 2004-01-30 18:49:23.000000000 -0800 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_BEHAVIOR_H__ +#define __XFS_BEHAVIOR_H__ + +/* + * Header file used to associate behaviors with virtualized objects. + * + * A virtualized object is an internal, virtualized representation of + * OS entities such as persistent files, processes, or sockets. Examples + * of virtualized objects include vnodes, vprocs, and vsockets. Often + * a virtualized object is referred to simply as an "object." + * + * A behavior is essentially an implementation layer associated with + * an object. Multiple behaviors for an object are chained together, + * the order of chaining determining the order of invocation. Each + * behavior of a given object implements the same set of interfaces + * (e.g., the VOP interfaces). + * + * Behaviors may be dynamically inserted into an object's behavior chain, + * such that the addition is transparent to consumers that already have + * references to the object. Typically, a given behavior will be inserted + * at a particular location in the behavior chain. Insertion of new + * behaviors is synchronized with operations-in-progress (oip's) so that + * the oip's always see a consistent view of the chain. + * + * The term "interpostion" is used to refer to the act of inserting + * a behavior such that it interposes on (i.e., is inserted in front + * of) a particular other behavior. A key example of this is when a + * system implementing distributed single system image wishes to + * interpose a distribution layer (providing distributed coherency) + * in front of an object that is otherwise only accessed locally. + * + * Note that the traditional vnode/inode combination is simply a virtualized + * object that has exactly one associated behavior. + * + * Behavior synchronization is logic which is necessary under certain + * circumstances that there is no conflict between ongoing operations + * traversing the behavior chain and those dunamically modifying the + * behavior chain. Because behavior synchronization adds extra overhead + * to virtual operation invocation, we want to restrict, as much as + * we can, the requirement for this extra code, to those situations + * in which it is truly necessary. + * + * Behavior synchronization is needed whenever there's at least one class + * of object in the system for which: + * 1) multiple behaviors for a given object are supported, + * -- AND -- + * 2a) insertion of a new behavior can happen dynamically at any time during + * the life of an active object, + * -- AND -- + * 3a) insertion of a new behavior needs to synchronize with existing + * ops-in-progress. + * -- OR -- + * 3b) multiple different behaviors can be dynamically inserted at + * any time during the life of an active object + * -- OR -- + * 3c) removal of a behavior can occur at any time during the life of + * an active object. + * -- OR -- + * 2b) removal of a behavior can occur at any time during the life of an + * active object + * + */ + +struct bhv_head_lock; + +/* + * Behavior head. Head of the chain of behaviors. + * Contained within each virtualized object data structure. + */ +typedef struct bhv_head { + struct bhv_desc *bh_first; /* first behavior in chain */ + struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */ +} bhv_head_t; + +/* + * Behavior descriptor. Descriptor associated with each behavior. + * Contained within the behavior's private data structure. + */ +typedef struct bhv_desc { + void *bd_pdata; /* private data for this behavior */ + void *bd_vobj; /* virtual object associated with */ + void *bd_ops; /* ops for this behavior */ + struct bhv_desc *bd_next; /* next behavior in chain */ +} bhv_desc_t; + +/* + * Behavior identity field. A behavior's identity determines the position + * where it lives within a behavior chain, and it's always the first field + * of the behavior's ops vector. The optional id field further identifies the + * subsystem responsible for the behavior. + */ +typedef struct bhv_identity { + __u16 bi_id; /* owning subsystem id */ + __u16 bi_position; /* position in chain */ +} bhv_identity_t; + +typedef bhv_identity_t bhv_position_t; + +#define BHV_IDENTITY_INIT(id,pos) {id, pos} +#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos) + +/* + * Define boundaries of position values. + */ +#define BHV_POSITION_INVALID 0 /* invalid position number */ +#define BHV_POSITION_BASE 1 /* base (last) implementation layer */ +#define BHV_POSITION_TOP 63 /* top (first) implementation layer */ + +/* + * Plumbing macros. + */ +#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first) +#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next) +#define BHV_NEXTNULL(bdp) ((bdp)->bd_next) +#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj) +#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj) +#define BHV_PDATA(bdp) (bdp)->bd_pdata +#define BHV_OPS(bdp) (bdp)->bd_ops +#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops) +#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position) + +extern void bhv_head_init(bhv_head_t *, char *); +extern void bhv_head_destroy(bhv_head_t *); +extern int bhv_insert(bhv_head_t *, bhv_desc_t *); +extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); + +/* + * Initialize a new behavior descriptor. + * Arguments: + * bdp - pointer to behavior descriptor + * pdata - pointer to behavior's private data + * vobj - pointer to associated virtual object + * ops - pointer to ops for this behavior + */ +#define bhv_desc_init(bdp, pdata, vobj, ops) \ + { \ + (bdp)->bd_pdata = pdata; \ + (bdp)->bd_vobj = vobj; \ + (bdp)->bd_ops = ops; \ + (bdp)->bd_next = NULL; \ + } + +/* + * Remove a behavior descriptor from a behavior chain. + */ +#define bhv_remove(bhp, bdp) \ + { \ + if ((bhp)->bh_first == (bdp)) { \ + /* \ + * Remove from front of chain. \ + * Atomic wrt oip's. \ + */ \ + (bhp)->bh_first = (bdp)->bd_next; \ + } else { \ + /* remove from non-front of chain */ \ + bhv_remove_not_first(bhp, bdp); \ + } \ + (bdp)->bd_vobj = NULL; \ + } + +/* + * Behavior module prototypes. + */ +extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp); +extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops); +extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high); +extern bhv_desc_t * bhv_base(bhv_head_t *bhp); + +/* No bhv locking on Linux */ +#define bhv_lookup_unlocked bhv_lookup +#define bhv_base_unlocked bhv_base + +#endif /* __XFS_BEHAVIOR_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/xfs_bmap_btree.c linux-2.6.2-rc3/fs/xfs/xfs_bmap_btree.c --- linux-2.6.2-rc2/fs/xfs/xfs_bmap_btree.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_bmap_btree.c 2004-01-30 18:49:23.000000000 -0800 @@ -61,7 +61,7 @@ #include "xfs_error.h" #include "xfs_quota.h" -#ifdef DEBUG +#if defined(XFS_BMBT_TRACE) ktrace_t *xfs_bmbt_trace_buf; #endif diff -urN linux-2.6.2-rc2/fs/xfs/xfs_buf.h linux-2.6.2-rc3/fs/xfs/xfs_buf.h --- linux-2.6.2-rc2/fs/xfs/xfs_buf.h 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_buf.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_BUF_H__ -#define __XFS_BUF_H__ - -/* These are just for xfs_syncsub... it sets an internal variable - * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t - */ -#define XFS_B_ASYNC PBF_ASYNC -#define XFS_B_DELWRI PBF_DELWRI -#define XFS_B_READ PBF_READ -#define XFS_B_WRITE PBF_WRITE -#define XFS_B_STALE PBF_STALE - -#define XFS_BUF_TRYLOCK PBF_TRYLOCK -#define XFS_INCORE_TRYLOCK PBF_TRYLOCK -#define XFS_BUF_LOCK PBF_LOCK -#define XFS_BUF_MAPPED PBF_MAPPED - -#define BUF_BUSY PBF_DONT_BLOCK - -#define XFS_BUF_BFLAGS(x) ((x)->pb_flags) -#define XFS_BUF_ZEROFLAGS(x) \ - ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI)) - -#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) -#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) -#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE) -#define XFS_BUF_SUPER_STALE(x) do { \ - XFS_BUF_STALE(x); \ - xfs_buf_undelay(x); \ - XFS_BUF_DONE(x); \ - } while (0) - -#define XFS_BUF_MANAGE PBF_FS_MANAGED -#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED) - -static inline void xfs_buf_undelay(page_buf_t *pb) -{ - if (pb->pb_flags & PBF_DELWRI) { - if (pb->pb_list.next != &pb->pb_list) { - pagebuf_delwri_dequeue(pb); - pagebuf_rele(pb); - } else { - pb->pb_flags &= ~PBF_DELWRI; - } - } -} - -#define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI) -#define XFS_BUF_UNDELAYWRITE(x) xfs_buf_undelay(x) -#define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI) - -#define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no) -#define XFS_BUF_GETERROR(x) pagebuf_geterror(x) -#define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0) - -#define XFS_BUF_DONE(x) ((x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE)) -#define XFS_BUF_UNDONE(x) ((x)->pb_flags |= PBF_PARTIAL|PBF_NONE) -#define XFS_BUF_ISDONE(x) (!(PBF_NOT_DONE(x))) - -#define XFS_BUF_BUSY(x) ((x)->pb_flags |= PBF_FORCEIO) -#define XFS_BUF_UNBUSY(x) ((x)->pb_flags &= ~PBF_FORCEIO) -#define XFS_BUF_ISBUSY(x) (1) - -#define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC) -#define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) -#define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) - -#define XFS_BUF_FLUSH(x) ((x)->pb_flags |= PBF_FLUSH) -#define XFS_BUF_UNFLUSH(x) ((x)->pb_flags &= ~PBF_FLUSH) -#define XFS_BUF_ISFLUSH(x) ((x)->pb_flags & PBF_FLUSH) - -#define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") -#define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") -#define XFS_BUF_ISSHUT(x) (0) - -#define XFS_BUF_HOLD(x) pagebuf_hold(x) -#define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ) -#define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ) -#define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ) - -#define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE) -#define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE) -#define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE) - -#define XFS_BUF_ISUNINITIAL(x) (0) -#define XFS_BUF_UNUNINITIAL(x) (0) - -#define XFS_BUF_BP_ISMAPPED(bp) 1 - -typedef struct page_buf_s xfs_buf_t; -#define xfs_buf page_buf_s - -typedef struct pb_target xfs_buftarg_t; -#define xfs_buftarg pb_target - -#define XFS_BUF_DATAIO(x) ((x)->pb_flags |= PBF_FS_DATAIOD) -#define XFS_BUF_UNDATAIO(x) ((x)->pb_flags &= ~PBF_FS_DATAIOD) - -#define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone -#define XFS_BUF_SET_IODONE_FUNC(buf, func) \ - (buf)->pb_iodone = (func) -#define XFS_BUF_CLR_IODONE_FUNC(buf) \ - (buf)->pb_iodone = NULL -#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \ - (buf)->pb_strat = (func) -#define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \ - (buf)->pb_strat = NULL - -#define XFS_BUF_FSPRIVATE(buf, type) \ - ((type)(buf)->pb_fspriv) -#define XFS_BUF_SET_FSPRIVATE(buf, value) \ - (buf)->pb_fspriv = (void *)(value) -#define XFS_BUF_FSPRIVATE2(buf, type) \ - ((type)(buf)->pb_fspriv2) -#define XFS_BUF_SET_FSPRIVATE2(buf, value) \ - (buf)->pb_fspriv2 = (void *)(value) -#define XFS_BUF_FSPRIVATE3(buf, type) \ - ((type)(buf)->pb_fspriv3) -#define XFS_BUF_SET_FSPRIVATE3(buf, value) \ - (buf)->pb_fspriv3 = (void *)(value) -#define XFS_BUF_SET_START(buf) - -#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \ - (buf)->pb_relse = (value) - -#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr) - -extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset) -{ - if (bp->pb_flags & PBF_MAPPED) - return XFS_BUF_PTR(bp) + offset; - return (xfs_caddr_t) pagebuf_offset(bp, offset); -} - -#define XFS_BUF_SET_PTR(bp, val, count) \ - pagebuf_associate_memory(bp, val, count) -#define XFS_BUF_ADDR(bp) ((bp)->pb_bn) -#define XFS_BUF_SET_ADDR(bp, blk) \ - ((bp)->pb_bn = (page_buf_daddr_t)(blk)) -#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) -#define XFS_BUF_SET_OFFSET(bp, off) \ - ((bp)->pb_file_offset = (off)) -#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) -#define XFS_BUF_SET_COUNT(bp, cnt) \ - ((bp)->pb_count_desired = (cnt)) -#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) -#define XFS_BUF_SET_SIZE(bp, cnt) \ - ((bp)->pb_buffer_length = (cnt)) -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) -#define XFS_BUF_SET_VTYPE(bp, type) -#define XFS_BUF_SET_REF(bp, ref) - -#define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp) - -#define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp) -#define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0) -#define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp) -#define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp) -#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema); - -/* setup the buffer target from a buftarg structure */ -#define XFS_BUF_SET_TARGET(bp, target) \ - (bp)->pb_target = (target) -#define XFS_BUF_TARGET(bp) ((bp)->pb_target) -#define XFS_BUFTARG_NAME(target) \ - pagebuf_target_name(target) - -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) -#define XFS_BUF_SET_VTYPE(bp, type) -#define XFS_BUF_SET_REF(bp, ref) - -#define xfs_buf_read(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE) -#define xfs_buf_get(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE) - -#define xfs_buf_read_flags(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_READ | PBF_MAPPABLE | flags) -#define xfs_buf_get_flags(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_MAPPABLE | flags) - -static inline int xfs_bawrite(void *mp, page_buf_t *bp) -{ - bp->pb_fspriv3 = mp; - bp->pb_strat = xfs_bdstrat_cb; - xfs_buf_undelay(bp); - return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES); -} - -static inline void xfs_buf_relse(page_buf_t *bp) -{ - if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse) - pagebuf_unlock(bp); - pagebuf_rele(bp); -} - -#define xfs_bpin(bp) pagebuf_pin(bp) -#define xfs_bunpin(bp) pagebuf_unpin(bp) - -#define xfs_buftrace(id, bp) \ - pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) - -#define xfs_biodone(pb) \ - pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0) - -#define xfs_incore(buftarg,blkno,len,lockit) \ - pagebuf_find(buftarg, blkno ,len, lockit) - - -#define xfs_biomove(pb, off, len, data, rw) \ - pagebuf_iomove((pb), (off), (len), (data), \ - ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ) - -#define xfs_biozero(pb, off, len) \ - pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO) - - -static inline int XFS_bwrite(page_buf_t *pb) -{ - int iowait = (pb->pb_flags & PBF_ASYNC) == 0; - int error = 0; - - pb->pb_flags |= PBF_SYNC; - if (!iowait) - pb->pb_flags |= PBF_RUN_QUEUES; - - xfs_buf_undelay(pb); - pagebuf_iostrategy(pb); - if (iowait) { - error = pagebuf_iowait(pb); - xfs_buf_relse(pb); - } - return error; -} - -#define XFS_bdwrite(pb) \ - pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC) - -static inline int xfs_bdwrite(void *mp, page_buf_t *bp) -{ - bp->pb_strat = xfs_bdstrat_cb; - bp->pb_fspriv3 = mp; - - return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC); -} - -#define XFS_bdstrat(bp) pagebuf_iorequest(bp) - -#define xfs_iowait(pb) pagebuf_iowait(pb) - - -/* - * Go through all incore buffers, and release buffers - * if they belong to the given device. This is used in - * filesystem error handling to preserve the consistency - * of its metadata. - */ - -#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg) - -#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg) - -#define xfs_incore_relse(buftarg,delwri_only,wait) \ - xfs_relse_buftarg(buftarg) - -#define xfs_baread(target, rablkno, ralen) \ - pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK) - -#define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target)) -#define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target)) -#define xfs_buf_free(bp) pagebuf_free(bp) - -#endif /* __XFS_BUF_H__ */ diff -urN linux-2.6.2-rc2/fs/xfs/xfs_dir.c linux-2.6.2-rc3/fs/xfs/xfs_dir.c --- linux-2.6.2-rc2/fs/xfs/xfs_dir.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_dir.c 2004-01-30 18:49:24.000000000 -0800 @@ -162,7 +162,7 @@ xfs_dir_put_t put); STATIC int xfs_dir_node_replace(xfs_da_args_t *args); -#if defined(DEBUG) +#if defined(XFS_DIR_TRACE) ktrace_t *xfs_dir_trace_buf; #endif diff -urN linux-2.6.2-rc2/fs/xfs/xfs_dir2_trace.c linux-2.6.2-rc3/fs/xfs/xfs_dir2_trace.c --- linux-2.6.2-rc2/fs/xfs/xfs_dir2_trace.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_dir2_trace.c 2004-01-30 18:49:24.000000000 -0800 @@ -49,11 +49,9 @@ #include "xfs_da_btree.h" #include "xfs_dir2_trace.h" -#ifdef DEBUG +#ifdef XFS_DIR2_TRACE ktrace_t *xfs_dir2_trace_buf; -#endif /* DEBUG */ -#ifdef XFS_DIR2_TRACE /* * Enter something in the trace buffers. */ diff -urN linux-2.6.2-rc2/fs/xfs/xfs_iomap.c linux-2.6.2-rc3/fs/xfs/xfs_iomap.c --- linux-2.6.2-rc2/fs/xfs/xfs_iomap.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_iomap.c 2004-01-30 18:49:24.000000000 -0800 @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include "xfs.h" + +#include "xfs_fs.h" +#include "xfs_inum.h" +#include "xfs_log.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_dir.h" +#include "xfs_dir2.h" +#include "xfs_alloc.h" +#include "xfs_dmapi.h" +#include "xfs_quota.h" +#include "xfs_mount.h" +#include "xfs_alloc_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_ialloc_btree.h" +#include "xfs_btree.h" +#include "xfs_ialloc.h" +#include "xfs_attr_sf.h" +#include "xfs_dir_sf.h" +#include "xfs_dir2_sf.h" +#include "xfs_dinode.h" +#include "xfs_inode.h" +#include "xfs_bmap.h" +#include "xfs_bit.h" +#include "xfs_rtalloc.h" +#include "xfs_error.h" +#include "xfs_itable.h" +#include "xfs_rw.h" +#include "xfs_acl.h" +#include "xfs_cap.h" +#include "xfs_mac.h" +#include "xfs_attr.h" +#include "xfs_buf_item.h" +#include "xfs_trans_space.h" +#include "xfs_utils.h" +#include "xfs_iomap.h" + +#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ + << mp->m_writeio_log) +#define XFS_STRAT_WRITE_IMAPS 2 +#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP + +STATIC int +xfs_imap_to_bmap( + xfs_iocore_t *io, + xfs_off_t offset, + xfs_bmbt_irec_t *imap, + xfs_iomap_t *iomapp, + int imaps, /* Number of imap entries */ + int iomaps, /* Number of iomap entries */ + int flags) +{ + xfs_mount_t *mp; + xfs_fsize_t nisize; + int pbm; + xfs_fsblock_t start_block; + + mp = io->io_mount; + nisize = XFS_SIZE(mp, io); + if (io->io_new_size > nisize) + nisize = io->io_new_size; + + for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { + iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? + mp->m_rtdev_targp : mp->m_ddev_targp; + iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); + iomapp->iomap_delta = offset - iomapp->iomap_offset; + iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); + iomapp->iomap_flags = flags; + + start_block = imap->br_startblock; + if (start_block == HOLESTARTBLOCK) { + iomapp->iomap_bn = IOMAP_DADDR_NULL; + iomapp->iomap_flags = IOMAP_HOLE; + } else if (start_block == DELAYSTARTBLOCK) { + iomapp->iomap_bn = IOMAP_DADDR_NULL; + iomapp->iomap_flags = IOMAP_DELAY; + } else { + iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); + if (ISUNWRITTEN(imap)) + iomapp->iomap_flags |= IOMAP_UNWRITTEN; + } + + if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) { + iomapp->iomap_flags |= IOMAP_EOF; + } + + offset += iomapp->iomap_bsize - iomapp->iomap_delta; + } + return pbm; /* Return the number filled */ +} + +int +xfs_iomap( + xfs_iocore_t *io, + xfs_off_t offset, + ssize_t count, + int flags, + xfs_iomap_t *iomapp, + int *niomaps) +{ + xfs_mount_t *mp = io->io_mount; + xfs_fileoff_t offset_fsb, end_fsb; + int error = 0; + int lockmode = 0; + xfs_bmbt_irec_t imap; + int nimaps = 1; + int bmapi_flags = 0; + int iomap_flags = 0; + + if (XFS_FORCED_SHUTDOWN(mp)) + return XFS_ERROR(EIO); + + switch (flags & + (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | + BMAPI_UNWRITTEN | BMAPI_DEVICE)) { + case BMAPI_READ: + lockmode = XFS_LCK_MAP_SHARED(mp, io); + bmapi_flags = XFS_BMAPI_ENTIRE; + if (flags & BMAPI_IGNSTATE) + bmapi_flags |= XFS_BMAPI_IGSTATE; + break; + case BMAPI_WRITE: + lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; + bmapi_flags = 0; + XFS_ILOCK(mp, io, lockmode); + break; + case BMAPI_ALLOCATE: + lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; + bmapi_flags = XFS_BMAPI_ENTIRE; + /* Attempt non-blocking lock */ + if (flags & BMAPI_TRYLOCK) { + if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) + return XFS_ERROR(EAGAIN); + } else { + XFS_ILOCK(mp, io, lockmode); + } + break; + case BMAPI_UNWRITTEN: + goto phase2; + case BMAPI_DEVICE: + lockmode = XFS_LCK_MAP_SHARED(mp, io); + iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? + mp->m_rtdev_targp : mp->m_ddev_targp; + error = 0; + *niomaps = 1; + goto out; + default: + BUG(); + } + + ASSERT(offset <= mp->m_maxioffset); + if ((xfs_fsize_t)offset + count > mp->m_maxioffset) + count = mp->m_maxioffset - offset; + end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); + offset_fsb = XFS_B_TO_FSBT(mp, offset); + + error = XFS_BMAPI(mp, NULL, io, offset_fsb, + (xfs_filblks_t)(end_fsb - offset_fsb), + bmapi_flags, NULL, 0, &imap, + &nimaps, NULL); + + if (error) + goto out; + +phase2: + switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { + case BMAPI_WRITE: + /* If we found an extent, return it */ + if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) + break; + + if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { + error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, + count, flags, &imap, &nimaps, nimaps); + } else { + error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, + flags, &imap, &nimaps); + } + iomap_flags = IOMAP_NEW; + break; + case BMAPI_ALLOCATE: + /* If we found an extent, return it */ + XFS_IUNLOCK(mp, io, lockmode); + lockmode = 0; + + if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) + break; + + error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); + break; + case BMAPI_UNWRITTEN: + lockmode = 0; + error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); + nimaps = 0; + break; + } + + if (nimaps) { + *niomaps = xfs_imap_to_bmap(io, offset, &imap, + iomapp, nimaps, *niomaps, iomap_flags); + } else if (niomaps) { + *niomaps = 0; + } + +out: + if (lockmode) + XFS_IUNLOCK(mp, io, lockmode); + return XFS_ERROR(error); +} + +STATIC int +xfs_flush_space( + xfs_inode_t *ip, + int *fsynced, + int *ioflags) +{ + switch (*fsynced) { + case 0: + if (ip->i_delayed_blks) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_flush_inode(ip); + xfs_ilock(ip, XFS_ILOCK_EXCL); + *fsynced = 1; + } else { + *ioflags |= BMAPI_SYNC; + *fsynced = 2; + } + return 0; + case 1: + *fsynced = 2; + *ioflags |= BMAPI_SYNC; + return 0; + case 2: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_flush_device(ip); + xfs_ilock(ip, XFS_ILOCK_EXCL); + *fsynced = 3; + return 0; + } + return 1; +} + +int +xfs_iomap_write_direct( + xfs_inode_t *ip, + loff_t offset, + size_t count, + int flags, + xfs_bmbt_irec_t *ret_imap, + int *nmaps, + int found) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_iocore_t *io = &ip->i_iocore; + xfs_fileoff_t offset_fsb; + xfs_fileoff_t last_fsb; + xfs_filblks_t count_fsb; + xfs_fsize_t isize; + xfs_fsblock_t firstfsb; + int nimaps, maps; + int error; + int bmapi_flag; + int rt; + xfs_trans_t *tp; + xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; + xfs_bmap_free_t free_list; + int aeof; + xfs_filblks_t datablocks; + int committed; + int numrtextents; + uint resblks; + + /* + * Make sure that the dquots are there. This doesn't hold + * the ilock across a disk read. + */ + + error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); + if (error) + return XFS_ERROR(error); + + maps = min(XFS_WRITE_IMAPS, *nmaps); + nimaps = maps; + + isize = ip->i_d.di_size; + aeof = (offset + count) > isize; + + if (io->io_new_size > isize) + isize = io->io_new_size; + + offset_fsb = XFS_B_TO_FSBT(mp, offset); + last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); + count_fsb = last_fsb - offset_fsb; + if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { + xfs_fileoff_t map_last_fsb; + + map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; + + if (map_last_fsb < last_fsb) { + last_fsb = map_last_fsb; + count_fsb = last_fsb - offset_fsb; + } + ASSERT(count_fsb > 0); + } + + /* + * determine if reserving space on + * the data or realtime partition. + */ + if ((rt = XFS_IS_REALTIME_INODE(ip))) { + int sbrtextsize, iprtextsize; + + sbrtextsize = mp->m_sb.sb_rextsize; + iprtextsize = + ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; + numrtextents = (count_fsb + iprtextsize - 1); + do_div(numrtextents, sbrtextsize); + datablocks = 0; + } else { + datablocks = count_fsb; + numrtextents = 0; + } + + /* + * allocate and setup the transaction + */ + xfs_iunlock(ip, XFS_ILOCK_EXCL); + tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); + + resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); + + error = xfs_trans_reserve(tp, resblks, + XFS_WRITE_LOG_RES(mp), numrtextents, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + + /* + * check for running out of space + */ + if (error) + /* + * Free the transaction structure. + */ + xfs_trans_cancel(tp, 0); + + xfs_ilock(ip, XFS_ILOCK_EXCL); + + if (error) + goto error_out; /* Don't return in above if .. trans .., + need lock to return */ + + if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { + error = (EDQUOT); + goto error1; + } + nimaps = 1; + + bmapi_flag = XFS_BMAPI_WRITE; + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + + if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) + bmapi_flag |= XFS_BMAPI_PREALLOC; + + /* + * issue the bmapi() call to allocate the blocks + */ + XFS_BMAP_INIT(&free_list, &firstfsb); + imapp = &imap[0]; + error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, + bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); + if (error) { + goto error0; + } + + /* + * complete the transaction + */ + + error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); + if (error) { + goto error0; + } + + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); + if (error) { + goto error_out; + } + + /* copy any maps to caller's array and return any error. */ + if (nimaps == 0) { + error = (ENOSPC); + goto error_out; + } + + *ret_imap = imap[0]; + *nmaps = 1; + return 0; + + error0: /* Cancel bmap, unlock inode, and cancel trans */ + xfs_bmap_cancel(&free_list); + + error1: /* Just cancel transaction */ + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); + *nmaps = 0; /* nothing set-up here */ + +error_out: + return XFS_ERROR(error); +} + +int +xfs_iomap_write_delay( + xfs_inode_t *ip, + loff_t offset, + size_t count, + int ioflag, + xfs_bmbt_irec_t *ret_imap, + int *nmaps) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_iocore_t *io = &ip->i_iocore; + xfs_fileoff_t offset_fsb; + xfs_fileoff_t last_fsb; + xfs_fsize_t isize; + xfs_fsblock_t firstblock; + int nimaps; + int error; + xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; + int aeof; + int fsynced = 0; + + ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); + + /* + * Make sure that the dquots are there. This doesn't hold + * the ilock across a disk read. + */ + + error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); + if (error) + return XFS_ERROR(error); + +retry: + isize = ip->i_d.di_size; + if (io->io_new_size > isize) { + isize = io->io_new_size; + } + + aeof = 0; + offset_fsb = XFS_B_TO_FSBT(mp, offset); + last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); + /* + * If the caller is doing a write at the end of the file, + * then extend the allocation (and the buffer used for the write) + * out to the file system's write iosize. We clean up any extra + * space left over when the file is closed in xfs_inactive(). + * + * We don't bother with this for sync writes, because we need + * to minimize the amount we write for good performance. + */ + if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { + xfs_off_t aligned_offset; + unsigned int iosize; + xfs_fileoff_t ioalign; + + iosize = mp->m_writeio_blocks; + aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); + ioalign = XFS_B_TO_FSBT(mp, aligned_offset); + last_fsb = ioalign + iosize; + aeof = 1; + } + + nimaps = XFS_WRITE_IMAPS; + firstblock = NULLFSBLOCK; + + /* + * roundup the allocation request to m_dalign boundary if file size + * is greater that 512K and we are allocating past the allocation eof + */ + if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) { + int eof; + xfs_fileoff_t new_last_fsb; + new_last_fsb = roundup_64(last_fsb, mp->m_dalign); + error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); + if (error) { + return error; + } + if (eof) { + last_fsb = new_last_fsb; + } + } + + error = xfs_bmapi(NULL, ip, offset_fsb, + (xfs_filblks_t)(last_fsb - offset_fsb), + XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | + XFS_BMAPI_ENTIRE, &firstblock, 1, imap, + &nimaps, NULL); + /* + * This can be EDQUOT, if nimaps == 0 + */ + if (error && (error != ENOSPC)) { + return XFS_ERROR(error); + } + /* + * If bmapi returned us nothing, and if we didn't get back EDQUOT, + * then we must have run out of space. + */ + + if (nimaps == 0) { + if (xfs_flush_space(ip, &fsynced, &ioflag)) + return XFS_ERROR(ENOSPC); + + error = 0; + goto retry; + } + + *ret_imap = imap[0]; + *nmaps = 1; + return 0; +} + +/* + * Pass in a delayed allocate extent, convert it to real extents; + * return to the caller the extent we create which maps on top of + * the originating callers request. + * + * Called without a lock on the inode. + */ +int +xfs_iomap_write_allocate( + xfs_inode_t *ip, + xfs_bmbt_irec_t *map, + int *retmap) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_fileoff_t offset_fsb, last_block; + xfs_fileoff_t end_fsb, map_start_fsb; + xfs_fsblock_t first_block; + xfs_bmap_free_t free_list; + xfs_filblks_t count_fsb; + xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS]; + xfs_trans_t *tp; + int i, nimaps, committed; + int error = 0; + int nres; + + *retmap = 0; + + /* + * Make sure that the dquots are there. + */ + + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return XFS_ERROR(error); + + offset_fsb = map->br_startoff; + count_fsb = map->br_blockcount; + map_start_fsb = offset_fsb; + + XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); + + while (count_fsb != 0) { + /* + * Set up a transaction with which to allocate the + * backing store for the file. Do allocations in a + * loop until we get some space in the range we are + * interested in. The other space that might be allocated + * is in the delayed allocation extent on which we sit + * but before our buffer starts. + */ + + nimaps = 0; + while (nimaps == 0) { + tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); + nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); + error = xfs_trans_reserve(tp, nres, + XFS_WRITE_LOG_RES(mp), + 0, XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + + if (error == ENOSPC) { + error = xfs_trans_reserve(tp, 0, + XFS_WRITE_LOG_RES(mp), + 0, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + } + if (error) { + xfs_trans_cancel(tp, 0); + return XFS_ERROR(error); + } + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + + XFS_BMAP_INIT(&free_list, &first_block); + + nimaps = XFS_STRAT_WRITE_IMAPS; + /* + * Ensure we don't go beyond eof - it is possible + * the extents changed since we did the read call, + * we dropped the ilock in the interim. + */ + + end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size); + xfs_bmap_last_offset(NULL, ip, &last_block, + XFS_DATA_FORK); + last_block = XFS_FILEOFF_MAX(last_block, end_fsb); + if ((map_start_fsb + count_fsb) > last_block) { + count_fsb = last_block - map_start_fsb; + if (count_fsb == 0) { + error = EAGAIN; + goto trans_cancel; + } + } + + /* Go get the actual blocks */ + error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, + XFS_BMAPI_WRITE, &first_block, 1, + imap, &nimaps, &free_list); + + if (error) + goto trans_cancel; + + error = xfs_bmap_finish(&tp, &free_list, + first_block, &committed); + + if (error) + goto trans_cancel; + + error = xfs_trans_commit(tp, + XFS_TRANS_RELEASE_LOG_RES, NULL); + + if (error) + goto error0; + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + } + + /* + * See if we were able to allocate an extent that + * covers at least part of the callers request + */ + + for (i = 0; i < nimaps; i++) { + if ((map->br_startoff >= imap[i].br_startoff) && + (map->br_startoff < (imap[i].br_startoff + + imap[i].br_blockcount))) { + *map = imap[i]; + *retmap = 1; + XFS_STATS_INC(xs_xstrat_quick); + return 0; + } + count_fsb -= imap[i].br_blockcount; + } + + /* So far we have not mapped the requested part of the + * file, just surrounding data, try again. + */ + nimaps--; + offset_fsb = imap[nimaps].br_startoff + + imap[nimaps].br_blockcount; + map_start_fsb = offset_fsb; + } + +trans_cancel: + xfs_bmap_cancel(&free_list); + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); +error0: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return XFS_ERROR(error); +} + +int +xfs_iomap_write_unwritten( + xfs_inode_t *ip, + loff_t offset, + size_t count) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_trans_t *tp; + xfs_fileoff_t offset_fsb; + xfs_filblks_t count_fsb; + xfs_filblks_t numblks_fsb; + xfs_bmbt_irec_t imap; + int committed; + int error; + int nres; + int nimaps; + xfs_fsblock_t firstfsb; + xfs_bmap_free_t free_list; + + offset_fsb = XFS_B_TO_FSBT(mp, offset); + count_fsb = XFS_B_TO_FSB(mp, count); + + do { + nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); + + /* + * set up a transaction to convert the range of extents + * from unwritten to real. Do allocations in a loop until + * we have covered the range passed in. + */ + + tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); + error = xfs_trans_reserve(tp, nres, + XFS_WRITE_LOG_RES(mp), 0, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + if (error) { + xfs_trans_cancel(tp, 0); + goto error0; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + + /* + * Modify the unwritten extent state of the buffer. + */ + XFS_BMAP_INIT(&free_list, &firstfsb); + nimaps = 1; + error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, + XFS_BMAPI_WRITE, &firstfsb, + 1, &imap, &nimaps, &free_list); + if (error) + goto error_on_bmapi_transaction; + + error = xfs_bmap_finish(&(tp), &(free_list), + firstfsb, &committed); + if (error) + goto error_on_bmapi_transaction; + + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + if (error) + goto error0; + + if ((numblks_fsb = imap.br_blockcount) == 0) { + /* + * The numblks_fsb value should always get + * smaller, otherwise the loop is stuck. + */ + ASSERT(imap.br_blockcount); + break; + } + offset_fsb += numblks_fsb; + count_fsb -= numblks_fsb; + } while (count_fsb > 0); + + return 0; + +error_on_bmapi_transaction: + xfs_bmap_cancel(&free_list); + xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT)); + xfs_iunlock(ip, XFS_ILOCK_EXCL); +error0: + return XFS_ERROR(error); +} diff -urN linux-2.6.2-rc2/fs/xfs/xfs_log_recover.c linux-2.6.2-rc3/fs/xfs/xfs_log_recover.c --- linux-2.6.2-rc2/fs/xfs/xfs_log_recover.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_log_recover.c 2004-01-30 18:49:24.000000000 -0800 @@ -1531,7 +1531,7 @@ xlog_recover_item_t *first_item, *itemq, *itemq_next; xfs_buf_log_format_t *buf_f; xfs_buf_log_format_v1_t *obuf_f; - ushort flags; + ushort flags = 0; first_item = itemq = trans->r_itemq; trans->r_itemq = NULL; diff -urN linux-2.6.2-rc2/fs/xfs/xfs_types.h linux-2.6.2-rc3/fs/xfs/xfs_types.h --- linux-2.6.2-rc2/fs/xfs/xfs_types.h 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_types.h 2004-01-30 18:49:24.000000000 -0800 @@ -75,24 +75,6 @@ #error BITS_PER_LONG must be 32 or 64 #endif -/* - * Some types are conditional depending on the target system. - * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. - * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well - * as requiring XFS_BIG_BLKNOS to be set. - */ -#if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) -# define XFS_BIG_BLKNOS 1 -# if BITS_PER_LONG == 64 -# define XFS_BIG_INUMS 1 -# else -# define XFS_BIG_INUMS 0 -# endif -#else -# define XFS_BIG_BLKNOS 0 -# define XFS_BIG_INUMS 0 -#endif - #endif /* __KERNEL__ */ typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */ diff -urN linux-2.6.2-rc2/fs/xfs/xfs_vfsops.c linux-2.6.2-rc3/fs/xfs/xfs_vfsops.c --- linux-2.6.2-rc2/fs/xfs/xfs_vfsops.c 2004-01-30 18:49:15.000000000 -0800 +++ linux-2.6.2-rc3/fs/xfs/xfs_vfsops.c 2004-01-30 18:49:24.000000000 -0800 @@ -171,6 +171,25 @@ xfs_sysctl_unregister(); xfs_refcache_destroy(); +#ifdef XFS_DIR2_TRACE + ktrace_free(xfs_dir2_trace_buf); +#endif +#ifdef XFS_ATTR_TRACE + ktrace_free(xfs_attr_trace_buf); +#endif +#ifdef XFS_DIR_TRACE + ktrace_free(xfs_dir_trace_buf); +#endif +#ifdef XFS_BMBT_TRACE + ktrace_free(xfs_bmbt_trace_buf); +#endif +#ifdef XFS_BMAP_TRACE + ktrace_free(xfs_bmap_trace_buf); +#endif +#ifdef XFS_ALLOC_TRACE + ktrace_free(xfs_alloc_trace_buf); +#endif + kmem_cache_destroy(xfs_bmap_free_item_zone); kmem_cache_destroy(xfs_btree_cur_zone); kmem_cache_destroy(xfs_inode_zone); diff -urN linux-2.6.2-rc2/include/acpi/acconfig.h linux-2.6.2-rc3/include/acpi/acconfig.h --- linux-2.6.2-rc2/include/acpi/acconfig.h 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acconfig.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20031002 +#define ACPI_CA_VERSION 0x20040116 /* Maximum objects in the various object caches */ diff -urN linux-2.6.2-rc2/include/acpi/acdebug.h linux-2.6.2-rc3/include/acpi/acdebug.h --- linux-2.6.2-rc2/include/acpi/acdebug.h 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acdebug.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acdisasm.h linux-2.6.2-rc3/include/acpi/acdisasm.h --- linux-2.6.2-rc2/include/acpi/acdisasm.h 2004-01-08 22:59:42.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acdisasm.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acdispat.h linux-2.6.2-rc3/include/acpi/acdispat.h --- linux-2.6.2-rc2/include/acpi/acdispat.h 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acdispat.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acevents.h linux-2.6.2-rc3/include/acpi/acevents.h --- linux-2.6.2-rc2/include/acpi/acevents.h 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acevents.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -182,6 +182,17 @@ union acpi_operand_object *region_obj, u8 acpi_ns_is_locked); +acpi_status +acpi_ev_execute_reg_method ( + union acpi_operand_object *region_obj, + u32 function); + +acpi_status +acpi_ev_reg_run ( + acpi_handle obj_handle, + u32 level, + void *context, + void **return_value); /* * Evregini - Region initialization and setup diff -urN linux-2.6.2-rc2/include/acpi/acexcep.h linux-2.6.2-rc3/include/acpi/acexcep.h --- linux-2.6.2-rc2/include/acpi/acexcep.h 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acexcep.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acglobal.h linux-2.6.2-rc3/include/acpi/acglobal.h --- linux-2.6.2-rc2/include/acpi/acglobal.h 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acglobal.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -106,6 +106,9 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; + +/* Keep local copies of these FADT-based registers */ + ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; diff -urN linux-2.6.2-rc2/include/acpi/achware.h linux-2.6.2-rc3/include/acpi/achware.h --- linux-2.6.2-rc2/include/acpi/achware.h 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/achware.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acinterp.h linux-2.6.2-rc3/include/acpi/acinterp.h --- linux-2.6.2-rc2/include/acpi/acinterp.h 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acinterp.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/aclocal.h linux-2.6.2-rc3/include/acpi/aclocal.h --- linux-2.6.2-rc2/include/acpi/aclocal.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/aclocal.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acmacros.h linux-2.6.2-rc3/include/acpi/acmacros.h --- linux-2.6.2-rc2/include/acpi/acmacros.h 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acmacros.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,6 @@ /* * Data manipulation macros */ - #define ACPI_LOWORD(l) ((u16)(u32)(l)) #define ACPI_HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF)) #define ACPI_LOBYTE(l) ((u8)(u16)(l)) @@ -94,10 +93,18 @@ #endif #endif - /* - * Extract a byte of data using a pointer. Any more than a byte and we - * get into potential aligment issues -- see the STORE macros below - */ +/* + * printf() format helpers + */ + +/* Split 64-bit integer into two 32-bit values. use with %8,8_x%8.8X */ + +#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) + +/* + * Extract a byte of data using a pointer. Any more than a byte and we + * get into potential aligment issues -- see the STORE macros below + */ #define ACPI_GET8(addr) (*(u8*)(addr)) /* Pointer arithmetic */ @@ -129,7 +136,6 @@ * If the hardware supports the transfer of unaligned data, just do the store. * Otherwise, we have to move one byte at a time. */ - #ifdef ACPI_BIG_ENDIAN /* * Macros for big-endian machines @@ -299,7 +305,6 @@ /* * Fast power-of-two math macros for non-optimized compilers */ - #define _ACPI_DIV(value,power_of2) ((u32) ((value) >> (power_of2))) #define _ACPI_MUL(value,power_of2) ((u32) ((value) << (power_of2))) #define _ACPI_MOD(value,divisor) ((u32) ((value) & ((divisor) -1))) @@ -443,7 +448,6 @@ /* * Reporting macros that are never compiled out */ - #define ACPI_PARAM_LIST(pl) pl /* @@ -451,7 +455,6 @@ * _THIS_MODULE gets compiled out when ACPI_DEBUG_OUTPUT isn't defined, only * use it in debug mode. */ - #ifdef ACPI_DEBUG_OUTPUT #define ACPI_REPORT_INFO(fp) {acpi_ut_report_info(_THIS_MODULE,__LINE__,_COMPONENT); \ @@ -490,7 +493,6 @@ /* * Debug macros that are conditionally compiled */ - #ifdef ACPI_DEBUG_OUTPUT #define ACPI_MODULE_NAME(name) static char ACPI_UNUSED_VAR *_THIS_MODULE = name; @@ -500,7 +502,6 @@ * The first parameter should be the procedure name as a quoted string. This is declared * as a local string ("_proc_name) so that it can be also used by the function exit macros below. */ - #define ACPI_FUNCTION_NAME(a) struct acpi_debug_print_info _dbg; \ _dbg.component_id = _COMPONENT; \ _dbg.proc_name = a; \ @@ -562,7 +563,6 @@ /* * Generate INT3 on ACPI_ERROR (Debug only!) */ - #define ACPI_ERROR_BREAK #ifdef ACPI_ERROR_BREAK #define ACPI_BREAK_ON_ERROR(lvl) if ((lvl)&ACPI_ERROR) \ @@ -577,7 +577,6 @@ * 1) Debug print for the current component is enabled * 2) Debug error level or trace level for the print statement is enabled */ - #define ACPI_DEBUG_PRINT(pl) acpi_ut_debug_print ACPI_PARAM_LIST(pl) #define ACPI_DEBUG_PRINT_RAW(pl) acpi_ut_debug_print_raw ACPI_PARAM_LIST(pl) @@ -587,7 +586,6 @@ * This is the non-debug case -- make everything go away, * leaving no executable debug code! */ - #define ACPI_MODULE_NAME(name) #define _THIS_MODULE "" @@ -662,7 +660,6 @@ /* * Memory allocation tracking (DEBUG ONLY) */ - #ifndef ACPI_DBG_TRACK_ALLOCATIONS /* Memory allocation */ diff -urN linux-2.6.2-rc2/include/acpi/acnamesp.h linux-2.6.2-rc3/include/acpi/acnamesp.h --- linux-2.6.2-rc2/include/acpi/acnamesp.h 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acnamesp.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acobject.h linux-2.6.2-rc3/include/acpi/acobject.h --- linux-2.6.2-rc2/include/acpi/acobject.h 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acobject.h 2004-01-30 18:49:24.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -114,7 +114,7 @@ #define ACPI_COMMON_NOTIFY_INFO \ union acpi_operand_object *system_notify; /* Handler for system notifies */\ union acpi_operand_object *device_notify; /* Handler for driver notifies */\ - union acpi_operand_object *address_space; /* Handler for Address space */ + union acpi_operand_object *handler; /* Handler for Address space */ /****************************************************************************** @@ -214,7 +214,7 @@ ACPI_OBJECT_COMMON_HEADER u8 space_id; - union acpi_operand_object *address_space; /* Handler for region access */ + union acpi_operand_object *handler; /* Handler for region access */ struct acpi_namespace_node *node; /* containing object */ union acpi_operand_object *next; u32 length; @@ -464,21 +464,22 @@ /* Object descriptor types */ -#define ACPI_DESC_TYPE_CACHED 0x11 /* Used only when object is cached */ -#define ACPI_DESC_TYPE_STATE 0x20 -#define ACPI_DESC_TYPE_STATE_UPDATE 0x21 -#define ACPI_DESC_TYPE_STATE_PACKAGE 0x22 -#define ACPI_DESC_TYPE_STATE_CONTROL 0x23 -#define ACPI_DESC_TYPE_STATE_RPSCOPE 0x24 -#define ACPI_DESC_TYPE_STATE_PSCOPE 0x25 -#define ACPI_DESC_TYPE_STATE_WSCOPE 0x26 -#define ACPI_DESC_TYPE_STATE_RESULT 0x27 -#define ACPI_DESC_TYPE_STATE_NOTIFY 0x28 -#define ACPI_DESC_TYPE_STATE_THREAD 0x29 -#define ACPI_DESC_TYPE_WALK 0x44 -#define ACPI_DESC_TYPE_PARSER 0x66 -#define ACPI_DESC_TYPE_OPERAND 0x88 -#define ACPI_DESC_TYPE_NAMED 0xAA +#define ACPI_DESC_TYPE_CACHED 0x01 /* Used only when object is cached */ +#define ACPI_DESC_TYPE_STATE 0x02 +#define ACPI_DESC_TYPE_STATE_UPDATE 0x03 +#define ACPI_DESC_TYPE_STATE_PACKAGE 0x04 +#define ACPI_DESC_TYPE_STATE_CONTROL 0x05 +#define ACPI_DESC_TYPE_STATE_RPSCOPE 0x06 +#define ACPI_DESC_TYPE_STATE_PSCOPE 0x07 +#define ACPI_DESC_TYPE_STATE_WSCOPE 0x08 +#define ACPI_DESC_TYPE_STATE_RESULT 0x09 +#define ACPI_DESC_TYPE_STATE_NOTIFY 0x0A +#define ACPI_DESC_TYPE_STATE_THREAD 0x0B +#define ACPI_DESC_TYPE_WALK 0x0C +#define ACPI_DESC_TYPE_PARSER 0x0D +#define ACPI_DESC_TYPE_OPERAND 0x0E +#define ACPI_DESC_TYPE_NAMED 0x0F +#define ACPI_DESC_TYPE_MAX 0x0F union acpi_descriptor diff -urN linux-2.6.2-rc2/include/acpi/acoutput.h linux-2.6.2-rc3/include/acpi/acoutput.h --- linux-2.6.2-rc2/include/acpi/acoutput.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acoutput.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acparser.h linux-2.6.2-rc3/include/acpi/acparser.h --- linux-2.6.2-rc2/include/acpi/acparser.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acparser.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acpi.h linux-2.6.2-rc3/include/acpi/acpi.h --- linux-2.6.2-rc2/include/acpi/acpi.h 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acpi.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acpi_drivers.h linux-2.6.2-rc3/include/acpi/acpi_drivers.h --- linux-2.6.2-rc2/include/acpi/acpi_drivers.h 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acpi_drivers.h 2004-01-30 18:49:24.000000000 -0800 @@ -53,10 +53,6 @@ #define ACPI_PCI_COMPONENT 0x00400000 -/* ACPI PCI Root Bridge (pci_root.c) */ - -void acpi_pci_get_translations (struct acpi_pci_id* id, u64* mem_tra, u64* io_tra); - /* ACPI PCI Interrupt Link (pci_link.c) */ int acpi_pci_link_check (void); diff -urN linux-2.6.2-rc2/include/acpi/acpiosxf.h linux-2.6.2-rc3/include/acpi/acpiosxf.h --- linux-2.6.2-rc2/include/acpi/acpiosxf.h 2004-01-08 22:59:04.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acpiosxf.h 2004-01-30 18:49:24.000000000 -0800 @@ -9,7 +9,7 @@ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acpixf.h linux-2.6.2-rc3/include/acpi/acpixf.h --- linux-2.6.2-rc2/include/acpi/acpixf.h 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acpixf.h 2004-01-30 18:49:24.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acresrc.h linux-2.6.2-rc3/include/acpi/acresrc.h --- linux-2.6.2-rc2/include/acpi/acresrc.h 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acresrc.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acstruct.h linux-2.6.2-rc3/include/acpi/acstruct.h --- linux-2.6.2-rc2/include/acpi/acstruct.h 2004-01-08 22:59:08.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acstruct.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/actables.h linux-2.6.2-rc3/include/acpi/actables.h --- linux-2.6.2-rc2/include/acpi/actables.h 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/actables.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/actbl.h linux-2.6.2-rc3/include/acpi/actbl.h --- linux-2.6.2-rc2/include/acpi/actbl.h 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/actbl.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -165,6 +165,11 @@ u8 type; \ u8 length; +struct apic_header +{ + APIC_HEADER_DEF +}; + /* Values for MPS INTI flags */ #define POLARITY_CONFORMS 0 @@ -236,7 +241,7 @@ { APIC_HEADER_DEF u16 reserved; /* Reserved - must be zero */ - u32 address; /* APIC physical address */ + u64 address; /* APIC physical address */ }; struct madt_io_sapic diff -urN linux-2.6.2-rc2/include/acpi/actbl1.h linux-2.6.2-rc3/include/acpi/actbl1.h --- linux-2.6.2-rc2/include/acpi/actbl1.h 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/actbl1.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/actbl2.h linux-2.6.2-rc3/include/acpi/actbl2.h --- linux-2.6.2-rc2/include/acpi/actbl2.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/actbl2.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/actypes.h linux-2.6.2-rc3/include/acpi/actypes.h --- linux-2.6.2-rc2/include/acpi/actypes.h 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/actypes.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/acutils.h linux-2.6.2-rc3/include/acpi/acutils.h --- linux-2.6.2-rc2/include/acpi/acutils.h 2004-01-08 22:59:04.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/acutils.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -125,6 +125,14 @@ acpi_object_type type); char * +acpi_ut_get_node_name ( + void *object); + +char * +acpi_ut_get_descriptor_name ( + void *object); + +char * acpi_ut_get_object_type_name ( union acpi_operand_object *obj_desc); diff -urN linux-2.6.2-rc2/include/acpi/amlcode.h linux-2.6.2-rc3/include/acpi/amlcode.h --- linux-2.6.2-rc2/include/acpi/amlcode.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/amlcode.h 2004-01-30 18:49:24.000000000 -0800 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/amlresrc.h linux-2.6.2-rc3/include/acpi/amlresrc.h --- linux-2.6.2-rc2/include/acpi/amlresrc.h 2004-01-08 23:00:04.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/amlresrc.h 2004-01-30 18:49:24.000000000 -0800 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/platform/acenv.h linux-2.6.2-rc3/include/acpi/platform/acenv.h --- linux-2.6.2-rc2/include/acpi/platform/acenv.h 2004-01-08 22:59:18.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/platform/acenv.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/platform/acgcc.h linux-2.6.2-rc3/include/acpi/platform/acgcc.h --- linux-2.6.2-rc2/include/acpi/platform/acgcc.h 2004-01-08 23:00:05.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/platform/acgcc.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/platform/aclinux.h linux-2.6.2-rc3/include/acpi/platform/aclinux.h --- linux-2.6.2-rc2/include/acpi/platform/aclinux.h 2004-01-08 22:59:55.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/platform/aclinux.h 2004-01-30 18:49:24.000000000 -0800 @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2003, R. Byron Moore + * Copyright (C) 2000 - 2004, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -urN linux-2.6.2-rc2/include/acpi/processor.h linux-2.6.2-rc3/include/acpi/processor.h --- linux-2.6.2-rc2/include/acpi/processor.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/acpi/processor.h 2004-01-30 18:49:24.000000000 -0800 @@ -72,6 +72,8 @@ int platform_limit; u16 control_register; u16 status_register; + u8 control_register_bit_width; + u8 status_register_bit_width; int state_count; struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE]; struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE]; diff -urN linux-2.6.2-rc2/include/asm-arm/arch-sa1100/cerf.h linux-2.6.2-rc3/include/asm-arm/arch-sa1100/cerf.h --- linux-2.6.2-rc2/include/asm-arm/arch-sa1100/cerf.h 2004-01-08 23:00:13.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-arm/arch-sa1100/cerf.h 2004-01-30 18:49:24.000000000 -0800 @@ -1,110 +1,29 @@ +/* + * include/asm-arm/arch-sa1100/cerf.h + * + * 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. + * + * Apr-2003 : Removed some old PDA crud [FB] + */ #ifndef _INCLUDE_CERF_H_ #define _INCLUDE_CERF_H_ #include -#ifdef CONFIG_SA1100_CERF_CPLD +#define CERF_ETH_IO 0xf0000000 +#define CERF_ETH_IRQ IRQ_GPIO26 - -// Map sa1100fb.c to sa1100_frontlight.c - Not pretty, but necessary. -#define CERF_BACKLIGHT_ENABLE sa1100_fl_enable -#define CERF_BACKLIGHT_DISABLE sa1100_fl_disable - -// -// IO Pins for devices -// - -#define CERF_PDA_CPLD 0xf1000000 -#define CERF_PDA_CPLD_WRCLRINT (0x0) -#define CERF_PDA_CPLD_BACKLIGHT (0x2) -#define CERF_PDA_CPLD_SOUND_FREQ (0x4) -#define CERF_PDA_CPLD_KEYPAD_A (0x6) -#define CERF_PDA_CPLD_BATTFAULT (0x8) -#define CERF_PDA_CPLD_KEYPAD_B (0xa) -#define CERF_PDA_CPLD_SOUND_ENA (0xc) -#define CERF_PDA_CPLD_SOUND_RESET (0xe) - -#define GPIO_CF_BVD2 GPIO_GPIO (5) -#define GPIO_CF_BVD1 GPIO_GPIO (6) -#define GPIO_CF_RESET GPIO_GPIO (7) -#define GPIO_CF_IRQ GPIO_GPIO (8) -#define GPIO_CF_CD GPIO_GPIO (9) - -#define GPIO_PWR_SHUTDOWN GPIO_GPIO (25) - -#define UCB1200_GPIO_CONT_CS 0x0001 -#define UCB1200_GPIO_CONT_DOWN 0x0002 -#define UCB1200_GPIO_CONT_INC 0x0004 -#define UCB1200_GPIO_CONT_ENA 0x0008 -#define UCB1200_GPIO_LCD_RESET 0x0010 -#define UCB1200_GPIO_IRDA_ENABLE 0x0020 -#define UCB1200_GPIO_BT_ENABLE 0x0040 -#define UCB1200_GPIO_L3_DATA 0x0080 -#define UCB1200_GPIO_L3_CLOCK 0x0100 -#define UCB1200_GPIO_L3_MODE 0x0200 - -// -// IRQ for devices -// - -#define IRQ_UCB1200_CONT_CS IRQ_UCB1200_IO0 -#define IRQ_UCB1200_CONT_DOWN IRQ_UCB1200_IO1 -#define IRQ_UCB1200_CONT_INC IRQ_UCB1200_IO2 -#define IRQ_UCB1200_CONT_ENA IRQ_UCB1200_IO3 -#define IRQ_UCB1200_LCD_RESET IRQ_UCB1200_IO4 -#define IRQ_UCB1200_IRDA_ENABLE IRQ_UCB1200_IO5 -#define IRQ_UCB1200_BT_ENABLE IRQ_UCB1200_IO6 -#define IRQ_UCB1200_L3_DATA IRQ_UCB1200_IO7 -#define IRQ_UCB1200_L3_CLOCK IRQ_UCB1200_IO8 -#define IRQ_UCB1200_L3_MODE IRQ_UCB1200_IO9 - -#define IRQ_GPIO_CF_BVD2 IRQ_GPIO5 -#define IRQ_GPIO_CF_BVD1 IRQ_GPIO6 -#define IRQ_GPIO_CF_IRQ IRQ_GPIO8 -#define IRQ_GPIO_CF_CD IRQ_GPIO9 - -// -// Device parameters -// - -#define CERF_PDA_CPLD_SOUND_FREQ_8000 (0x01) -#define CERF_PDA_CPLD_SOUND_FREQ_11025 (0x05) -#define CERF_PDA_CPLD_SOUND_FREQ_16000 (0x02) -#define CERF_PDA_CPLD_SOUND_FREQ_22050 (0x06) -#define CERF_PDA_CPLD_SOUND_FREQ_32000 (0x03) -#define CERF_PDA_CPLD_SOUND_FREQ_44100 (0x07) -#define CERF_PDA_CPLD_SOUND_FREQ_48000 (0x0b) - -// -// General Functions -// - -#define CERF_PDA_CPLD_Get(x, y) (*((char*)(CERF_PDA_CPLD + (x))) & (y)) -#define CERF_PDA_CPLD_Set(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) | (y)) -#define CERF_PDA_CPLD_UnSet(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) & ~(y)) - - -#else // CONFIG_SA1100_CERF_CPLD - - -#define GPIO_CF_BVD2 GPIO_GPIO (19) -#define GPIO_CF_BVD1 GPIO_GPIO (20) -#define GPIO_CF_RESET 0 -#define GPIO_CF_IRQ GPIO_GPIO (22) -#define GPIO_CF_CD GPIO_GPIO (23) - -#define GPIO_LCD_RESET GPIO_GPIO (15) - -#define IRQ_GPIO_CF_BVD2 IRQ_GPIO19 -#define IRQ_GPIO_CF_BVD1 IRQ_GPIO20 -#define IRQ_GPIO_CF_IRQ IRQ_GPIO22 -#define IRQ_GPIO_CF_CD IRQ_GPIO23 - - -#endif // CONFIG_SA1100_CERF_CPLD - - -#define GPIO_UCB1200_IRQ GPIO_GPIO (18) -#define IRQ_GPIO_UCB1200_IRQ IRQ_GPIO18 +#define CERF_GPIO_CF_BVD2 GPIO_GPIO (19) +#define CERF_GPIO_CF_BVD1 GPIO_GPIO (20) +#define CERF_GPIO_CF_RESET GPIO_GPIO (21) +#define CERF_GPIO_CF_IRQ GPIO_GPIO (22) +#define CERF_GPIO_CF_CD GPIO_GPIO (23) + +#define CERF_IRQ_GPIO_CF_BVD2 IRQ_GPIO19 +#define CERF_IRQ_GPIO_CF_BVD1 IRQ_GPIO20 +#define CERF_IRQ_GPIO_CF_IRQ IRQ_GPIO22 +#define CERF_IRQ_GPIO_CF_CD IRQ_GPIO23 #endif // _INCLUDE_CERF_H_ diff -urN linux-2.6.2-rc2/include/asm-arm/assembler.h linux-2.6.2-rc3/include/asm-arm/assembler.h --- linux-2.6.2-rc2/include/asm-arm/assembler.h 2004-01-08 22:59:07.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-arm/assembler.h 2004-01-30 18:49:24.000000000 -0800 @@ -25,11 +25,25 @@ #ifndef __ARMEB__ #define pull lsr #define push lsl -#define byte(x) (x*8) +#define get_byte_0 lsl #0 +#define get_byte_1 lsr #8 +#define get_byte_2 lsr #16 +#define get_byte_3 lsr #24 +#define put_byte_0 lsl #0 +#define put_byte_1 lsl #8 +#define put_byte_2 lsl #16 +#define put_byte_3 lsl #24 #else #define pull lsl #define push lsr -#define byte(x) ((3-x)*8) +#define get_byte_0 lsr #24 +#define get_byte_1 lsr #16 +#define get_byte_2 lsr #8 +#define get_byte_3 lsl #0 +#define put_byte_0 lsl #24 +#define put_byte_1 lsl #16 +#define put_byte_2 lsl #8 +#define put_byte_3 lsl #0 #endif /* diff -urN linux-2.6.2-rc2/include/asm-arm/bitops.h linux-2.6.2-rc3/include/asm-arm/bitops.h --- linux-2.6.2-rc2/include/asm-arm/bitops.h 2004-01-08 22:59:05.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-arm/bitops.h 2004-01-30 18:49:24.000000000 -0800 @@ -29,7 +29,7 @@ * * First, the atomic bitops. These use native endian. */ -static inline void ____atomic_set_bit(unsigned int bit, unsigned long *p) +static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); @@ -41,7 +41,7 @@ local_irq_restore(flags); } -static inline void ____atomic_clear_bit(unsigned int bit, unsigned long *p) +static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); @@ -53,7 +53,7 @@ local_irq_restore(flags); } -static inline void ____atomic_change_bit(unsigned int bit, unsigned long *p) +static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); @@ -66,7 +66,7 @@ } static inline int -____atomic_test_and_set_bit(unsigned int bit, unsigned long *p) +____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned int res; @@ -83,7 +83,7 @@ } static inline int -____atomic_test_and_clear_bit(unsigned int bit, unsigned long *p) +____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned int res; @@ -100,7 +100,7 @@ } static inline int -____atomic_test_and_change_bit(unsigned int bit, unsigned long *p) +____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned int res; @@ -171,7 +171,7 @@ /* * This routine doesn't need to be atomic. */ -static inline int __test_bit(int nr, const unsigned long * p) +static inline int __test_bit(int nr, const volatile unsigned long * p) { return (p[nr >> 5] >> (nr & 31)) & 1UL; } @@ -204,24 +204,24 @@ /* * Little endian assembly bitops. nr = 0 -> byte 0 bit 0. */ -extern void _set_bit_le(int nr, unsigned long * p); -extern void _clear_bit_le(int nr, unsigned long * p); -extern void _change_bit_le(int nr, unsigned long * p); -extern int _test_and_set_bit_le(int nr, unsigned long * p); -extern int _test_and_clear_bit_le(int nr, unsigned long * p); -extern int _test_and_change_bit_le(int nr, unsigned long * p); +extern void _set_bit_le(int nr, volatile unsigned long * p); +extern void _clear_bit_le(int nr, volatile unsigned long * p); +extern void _change_bit_le(int nr, volatile unsigned long * p); +extern int _test_and_set_bit_le(int nr, volatile unsigned long * p); +extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p); +extern int _test_and_change_bit_le(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_le(void * p, unsigned size); extern int _find_next_zero_bit_le(void * p, int size, int offset); /* * Big endian assembly bitops. nr = 0 -> byte 3 bit 0. */ -extern void _set_bit_be(int nr, unsigned long * p); -extern void _clear_bit_be(int nr, unsigned long * p); -extern void _change_bit_be(int nr, unsigned long * p); -extern int _test_and_set_bit_be(int nr, unsigned long * p); -extern int _test_and_clear_bit_be(int nr, unsigned long * p); -extern int _test_and_change_bit_be(int nr, unsigned long * p); +extern void _set_bit_be(int nr, volatile unsigned long * p); +extern void _clear_bit_be(int nr, volatile unsigned long * p); +extern void _change_bit_be(int nr, volatile unsigned long * p); +extern int _test_and_set_bit_be(int nr, volatile unsigned long * p); +extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p); +extern int _test_and_change_bit_be(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_be(void * p, unsigned size); extern int _find_next_zero_bit_be(void * p, int size, int offset); diff -urN linux-2.6.2-rc2/include/asm-arm/cacheflush.h linux-2.6.2-rc3/include/asm-arm/cacheflush.h --- linux-2.6.2-rc2/include/asm-arm/cacheflush.h 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-arm/cacheflush.h 2004-01-30 18:49:24.000000000 -0800 @@ -209,8 +209,21 @@ #endif +/* + * flush_cache_vmap() is used when creating mappings (eg, via vmap, + * vmalloc, ioremap etc) in kernel space for pages. Since the + * direct-mappings of these pages may contain cached data, we need + * to do a full cache flush to ensure that writebacks don't corrupt + * data placed into these pages via the new mappings. + */ #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() + +/* + * Copy user data from/to a page which is mapped into a different + * processes address space. Really, we want to allow our "user + * space" model to handle this. + */ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { memcpy(dst, src, len); \ flush_icache_user_range(vma, page, vaddr, len); \ diff -urN linux-2.6.2-rc2/include/asm-arm/thread_info.h linux-2.6.2-rc3/include/asm-arm/thread_info.h --- linux-2.6.2-rc2/include/asm-arm/thread_info.h 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-arm/thread_info.h 2004-01-30 18:49:24.000000000 -0800 @@ -51,8 +51,9 @@ __u32 cpu; /* cpu */ __u32 cpu_domain; /* cpu domain */ struct cpu_context_save cpu_context; /* cpu context */ - struct restart_block restart_block; + __u8 used_cp[16]; /* thread used copro */ union fp_state fpstate; + struct restart_block restart_block; }; #define INIT_THREAD_INFO(tsk) \ @@ -107,7 +108,8 @@ #define TI_CPU 20 #define TI_CPU_DOMAIN 24 #define TI_CPU_SAVE 28 -#define TI_FPSTATE 76 +#define TI_USED_MATH 76 +#define TI_FPSTATE (TI_USED_MATH+16) #endif diff -urN linux-2.6.2-rc2/include/asm-i386/acpi.h linux-2.6.2-rc3/include/asm-i386/acpi.h --- linux-2.6.2-rc2/include/asm-i386/acpi.h 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-i386/acpi.h 2004-01-30 18:49:24.000000000 -0800 @@ -109,7 +109,7 @@ #ifdef CONFIG_ACPI_BOOT extern int acpi_lapic; extern int acpi_ioapic; - +extern int acpi_noirq; /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ #define FIX_ACPI_PAGES 4 @@ -139,6 +139,14 @@ #endif +#ifdef CONFIG_ACPI_PCI +static inline void acpi_noirq_set(void) { acpi_noirq = 1; } +extern int acpi_irq_balance_set(char *str); +#else +static inline void acpi_noirq_set(void) { } +static inline int acpi_irq_balance_set(char *str) { return 0; } +#endif + #ifdef CONFIG_ACPI_SLEEP /* routines for saving/restoring kernel state */ diff -urN linux-2.6.2-rc2/include/asm-i386/system.h linux-2.6.2-rc3/include/asm-i386/system.h --- linux-2.6.2-rc2/include/asm-i386/system.h 2004-01-08 22:59:03.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-i386/system.h 2004-01-30 18:49:24.000000000 -0800 @@ -470,6 +470,7 @@ extern unsigned long dmi_broken; extern int is_sony_vaio_laptop; +extern int es7000_plat; #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002 diff -urN linux-2.6.2-rc2/include/asm-ia64/a.out.h linux-2.6.2-rc3/include/asm-ia64/a.out.h --- linux-2.6.2-rc2/include/asm-ia64/a.out.h 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/a.out.h 2004-01-30 18:49:24.000000000 -0800 @@ -7,8 +7,8 @@ * probably would be better to clean up binfmt_elf.c so it does not * necessarily depend on there being a.out support. * - * Copyright (C) 1998-2002 Hewlett-Packard Co - * David Mosberger-Tang + * Modified 1998-2002 + * David Mosberger-Tang , Hewlett-Packard Co. */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/bugs.h linux-2.6.2-rc3/include/asm-ia64/bugs.h --- linux-2.6.2-rc2/include/asm-ia64/bugs.h 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/bugs.h 2004-01-30 18:49:24.000000000 -0800 @@ -4,8 +4,10 @@ * Needs: * void check_bugs(void); * - * Copyright (C) 1998, 1999, 2003 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998, 1999, 2003 + * David Mosberger-Tang , Hewlett-Packard Co. */ #ifndef _ASM_IA64_BUGS_H #define _ASM_IA64_BUGS_H diff -urN linux-2.6.2-rc2/include/asm-ia64/byteorder.h linux-2.6.2-rc3/include/asm-ia64/byteorder.h --- linux-2.6.2-rc2/include/asm-ia64/byteorder.h 2004-01-30 18:49:16.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/byteorder.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_BYTEORDER_H /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co. */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/checksum.h linux-2.6.2-rc3/include/asm-ia64/checksum.h --- linux-2.6.2-rc2/include/asm-ia64/checksum.h 2004-01-08 22:59:02.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/checksum.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_CHECKSUM_H /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co */ /* diff -urN linux-2.6.2-rc2/include/asm-ia64/current.h linux-2.6.2-rc3/include/asm-ia64/current.h --- linux-2.6.2-rc2/include/asm-ia64/current.h 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/current.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_CURRENT_H /* - * Copyright (C) 1998-2000 Hewlett-Packard Co - * David Mosberger-Tang + * Modified 1998-2000 + * David Mosberger-Tang , Hewlett-Packard Co */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/errno.h linux-2.6.2-rc3/include/asm-ia64/errno.h --- linux-2.6.2-rc2/include/asm-ia64/errno.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/errno.h 2004-01-30 18:49:24.000000000 -0800 @@ -1,13 +1 @@ -#ifndef _ASM_IA64_ERRNO_H -#define _ASM_IA64_ERRNO_H - -/* - * This is derived from the Linux/x86 version. - * - * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co - * David Mosberger-Tang - */ - #include - -#endif /* _ASM_IA64_ERRNO_H */ diff -urN linux-2.6.2-rc2/include/asm-ia64/fcntl.h linux-2.6.2-rc3/include/asm-ia64/fcntl.h --- linux-2.6.2-rc2/include/asm-ia64/fcntl.h 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/fcntl.h 2004-01-30 18:49:24.000000000 -0800 @@ -1,10 +1,10 @@ #ifndef _ASM_IA64_FCNTL_H #define _ASM_IA64_FCNTL_H /* - * This is mostly compatible with Linux/x86. + * Based on . * - * Copyright (C) 1998-2000 Hewlett-Packard Co - * Copyright (C) 1998-2000 David Mosberger-Tang + * Modified 1998-2000 + * David Mosberger-Tang , Hewlett-Packard Co. */ /* diff -urN linux-2.6.2-rc2/include/asm-ia64/ioctl.h linux-2.6.2-rc3/include/asm-ia64/ioctl.h --- linux-2.6.2-rc2/include/asm-ia64/ioctl.h 2004-01-08 22:59:27.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/ioctl.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,10 +2,10 @@ #define _ASM_IA64_IOCTL_H /* - * This is mostly derived from the Linux/x86 version. + * Based on . * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co */ /* ioctl command encoding: 32 bits total, command in lower 16 bits, diff -urN linux-2.6.2-rc2/include/asm-ia64/ioctls.h linux-2.6.2-rc3/include/asm-ia64/ioctls.h --- linux-2.6.2-rc2/include/asm-ia64/ioctls.h 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/ioctls.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,10 @@ #define _ASM_IA64_IOCTLS_H /* - * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co - * David Mosberger-Tang + * Based on + * + * Modified 1998, 1999, 2002 + * David Mosberger-Tang , Hewlett-Packard Co */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/machvec.h linux-2.6.2-rc3/include/asm-ia64/machvec.h --- linux-2.6.2-rc2/include/asm-ia64/machvec.h 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/machvec.h 2004-01-30 18:49:24.000000000 -0800 @@ -28,6 +28,7 @@ typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *); typedef void ia64_mv_log_print_t (void); typedef void ia64_mv_send_ipi_t (int, int, int, int); +typedef void ia64_mv_timer_interrupt_t (int, void *, struct pt_regs *); typedef void ia64_mv_global_tlb_purge_t (unsigned long, unsigned long, unsigned long); typedef struct irq_desc *ia64_mv_irq_desc (unsigned int); typedef u8 ia64_mv_irq_to_vector (u8); @@ -90,6 +91,7 @@ # define platform_cmci_handler ia64_mv.cmci_handler # define platform_log_print ia64_mv.log_print # define platform_send_ipi ia64_mv.send_ipi +# define platform_timer_interrupt ia64_mv.timer_interrupt # define platform_global_tlb_purge ia64_mv.global_tlb_purge # define platform_dma_init ia64_mv.dma_init # define platform_dma_alloc_coherent ia64_mv.dma_alloc_coherent @@ -131,6 +133,7 @@ ia64_mv_cmci_handler_t *cmci_handler; ia64_mv_log_print_t *log_print; ia64_mv_send_ipi_t *send_ipi; + ia64_mv_timer_interrupt_t *timer_interrupt; ia64_mv_global_tlb_purge_t *global_tlb_purge; ia64_mv_dma_init *dma_init; ia64_mv_dma_alloc_coherent *dma_alloc_coherent; @@ -168,6 +171,7 @@ platform_cmci_handler, \ platform_log_print, \ platform_send_ipi, \ + platform_timer_interrupt, \ platform_global_tlb_purge, \ platform_dma_init, \ platform_dma_alloc_coherent, \ @@ -243,6 +247,9 @@ #ifndef platform_send_ipi # define platform_send_ipi ia64_send_ipi /* default to architected version */ #endif +#ifndef platform_timer_interrupt +# define platform_timer_interrupt ((ia64_mv_timer_interrupt_t *) machvec_noop) +#endif #ifndef platform_global_tlb_purge # define platform_global_tlb_purge ia64_global_tlb_purge /* default to architected version */ #endif diff -urN linux-2.6.2-rc2/include/asm-ia64/machvec_sn1.h linux-2.6.2-rc3/include/asm-ia64/machvec_sn1.h --- linux-2.6.2-rc2/include/asm-ia64/machvec_sn1.h 2004-01-08 22:59:46.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/machvec_sn1.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan - */ - -#ifndef _ASM_IA64_MACHVEC_SN1_h -#define _ASM_IA64_MACHVEC_SN1_h - -extern ia64_mv_setup_t sn1_setup; -extern ia64_mv_cpu_init_t sn_cpu_init; -extern ia64_mv_irq_init_t sn1_irq_init; -extern ia64_mv_send_ipi_t sn1_send_IPI; -extern ia64_mv_global_tlb_purge_t sn1_global_tlb_purge; -extern ia64_mv_inb_t sn1_inb; -extern ia64_mv_inw_t sn1_inw; -extern ia64_mv_inl_t sn1_inl; -extern ia64_mv_outb_t sn1_outb; -extern ia64_mv_outw_t sn1_outw; -extern ia64_mv_outl_t sn1_outl; -extern ia64_mv_dma_alloc_coherent sn1_dma_alloc_coherent; -extern ia64_mv_dma_free_coherent sn1_dma_free_coherent; -extern ia64_mv_dma_map_single sn1_dma_map_single; -extern ia64_mv_dma_unmap_single sn1_dma_unmap_single; -extern ia64_mv_dma_map_sg sn1_dma_map_sg; -extern ia64_mv_dma_unmap_sg sn1_dma_unmap_sg; -extern ia64_mv_dma_sync_single sn1_dma_sync_single; -extern ia64_mv_dma_sync_sg sn1_dma_sync_sg; - -/* - * This stuff has dual use! - * - * For a generic kernel, the macros are used to initialize the - * platform's machvec structure. When compiling a non-generic kernel, - * the macros are used directly. - */ -#define platform_name "sn1" -#define platform_setup sn1_setup -#define platform_cpu_init sn_cpu_init -#define platform_irq_init sn1_irq_init -#define platform_send_ipi sn1_send_IPI -#define platform_global_tlb_purge sn1_global_tlb_purge -#define platform_inb sn1_inb -#define platform_inw sn1_inw -#define platform_inl sn1_inl -#define platform_outb sn1_outb -#define platform_outw sn1_outw -#define platform_outl sn1_outl -#define platform_dma_init machvec_noop -#define platform_dma_alloc_coherent sn1_dma_alloc_coherent -#define platform_dma_free_coherent sn1_dma_free_coherent -#define platform_dma_map_single sn1_dma_map_single -#define platform_dma_unmap_single sn1_dma_unmap_single -#define platform_dma_map_sg sn1_dma_map_sg -#define platform_dma_unmap_sg sn1_dma_unmap_sg -#define platform_dma_sync_single sn1_dma_sync_single -#define platform_dma_sync_sg sn1_dma_sync_sg - -#endif /* _ASM_IA64_MACHVEC_SN1_h */ diff -urN linux-2.6.2-rc2/include/asm-ia64/machvec_sn2.h linux-2.6.2-rc3/include/asm-ia64/machvec_sn2.h --- linux-2.6.2-rc2/include/asm-ia64/machvec_sn2.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/machvec_sn2.h 2004-01-30 18:49:24.000000000 -0800 @@ -37,6 +37,7 @@ extern ia64_mv_cpu_init_t sn_cpu_init; extern ia64_mv_irq_init_t sn_irq_init; extern ia64_mv_send_ipi_t sn2_send_IPI; +extern ia64_mv_timer_interrupt_t sn_timer_interrupt; extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge; extern ia64_mv_irq_desc sn_irq_desc; extern ia64_mv_irq_to_vector sn_irq_to_vector; @@ -73,6 +74,7 @@ #define platform_cpu_init sn_cpu_init #define platform_irq_init sn_irq_init #define platform_send_ipi sn2_send_IPI +#define platform_timer_interrupt sn_timer_interrupt #define platform_global_tlb_purge sn2_global_tlb_purge #define platform_pci_fixup sn_pci_fixup #define platform_inb __sn_inb diff -urN linux-2.6.2-rc2/include/asm-ia64/mman.h linux-2.6.2-rc3/include/asm-ia64/mman.h --- linux-2.6.2-rc2/include/asm-ia64/mman.h 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/mman.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,10 @@ #define _ASM_IA64_MMAN_H /* - * Copyright (C) 1998-2000, 2002 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998-2000, 2002 + * David Mosberger-Tang , Hewlett-Packard Co */ #define PROT_READ 0x1 /* page can be read */ diff -urN linux-2.6.2-rc2/include/asm-ia64/namei.h linux-2.6.2-rc3/include/asm-ia64/namei.h --- linux-2.6.2-rc2/include/asm-ia64/namei.h 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/namei.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_NAMEI_H /* - * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co - * David Mosberger-Tang + * Modified 1998, 1999, 2001 + * David Mosberger-Tang , Hewlett-Packard Co */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/numa.h linux-2.6.2-rc3/include/asm-ia64/numa.h --- linux-2.6.2-rc2/include/asm-ia64/numa.h 2004-01-30 18:49:16.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/numa.h 2004-01-30 18:49:24.000000000 -0800 @@ -23,8 +23,8 @@ #include -extern volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; -extern volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; +extern u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; +extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; /* Stuff below this line could be architecture independent */ diff -urN linux-2.6.2-rc2/include/asm-ia64/param.h linux-2.6.2-rc3/include/asm-ia64/param.h --- linux-2.6.2-rc2/include/asm-ia64/param.h 2004-01-08 22:59:34.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/param.h 2004-01-30 18:49:24.000000000 -0800 @@ -4,8 +4,10 @@ /* * Fundamental kernel parameters. * - * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998, 1999, 2002-2003 + * David Mosberger-Tang , Hewlett-Packard Co */ #define EXEC_PAGESIZE 65536 diff -urN linux-2.6.2-rc2/include/asm-ia64/poll.h linux-2.6.2-rc3/include/asm-ia64/poll.h --- linux-2.6.2-rc2/include/asm-ia64/poll.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/poll.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,10 +2,10 @@ #define _ASM_IA64_POLL_H /* - * poll(2) bit definitions. Chosen to be compatible with Linux/x86. + * poll(2) bit definitions. Based on . * - * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co - * David Mosberger-Tang + * Modified 1998, 1999, 2002 + * David Mosberger-Tang , Hewlett-Packard Co */ #define POLLIN 0x0001 diff -urN linux-2.6.2-rc2/include/asm-ia64/posix_types.h linux-2.6.2-rc3/include/asm-ia64/posix_types.h --- linux-2.6.2-rc2/include/asm-ia64/posix_types.h 2004-01-08 22:59:19.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/posix_types.h 2004-01-30 18:49:24.000000000 -0800 @@ -6,8 +6,10 @@ * be a little careful about namespace pollution etc. Also, we cannot * assume GCC is being used. * - * Copyright (C) 1998-2000, 2003 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998-2000, 2003 + * David Mosberger-Tang , Hewlett-Packard Co */ typedef unsigned long __kernel_ino_t; diff -urN linux-2.6.2-rc2/include/asm-ia64/processor.h linux-2.6.2-rc3/include/asm-ia64/processor.h --- linux-2.6.2-rc2/include/asm-ia64/processor.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/processor.h 2004-01-30 18:49:24.000000000 -0800 @@ -53,12 +53,6 @@ */ #define TASK_UNMAPPED_BASE (current->thread.map_base) -/* - * Bus types - */ -#define MCA_bus 0 -#define MCA_bus__is_a_macro /* for versions in ksyms.c */ - #define IA64_THREAD_FPH_VALID (__IA64_UL(1) << 0) /* floating-point high state valid? */ #define IA64_THREAD_DBG_VALID (__IA64_UL(1) << 1) /* debug registers valid? */ #define IA64_THREAD_PM_VALID (__IA64_UL(1) << 2) /* performance registers valid? */ diff -urN linux-2.6.2-rc2/include/asm-ia64/resource.h linux-2.6.2-rc3/include/asm-ia64/resource.h --- linux-2.6.2-rc2/include/asm-ia64/resource.h 2004-01-08 22:59:55.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/resource.h 2004-01-30 18:49:24.000000000 -0800 @@ -4,8 +4,10 @@ /* * Resource limits * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Based on . + * + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/scatterlist.h linux-2.6.2-rc3/include/asm-ia64/scatterlist.h --- linux-2.6.2-rc2/include/asm-ia64/scatterlist.h 2004-01-08 22:59:42.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/scatterlist.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_SCATTERLIST_H /* - * Copyright (C) 1998-1999, 2001-2002 Hewlett-Packard Co - * David Mosberger-Tang + * Modified 1998-1999, 2001-2002 + * David Mosberger-Tang , Hewlett-Packard Co */ struct scatterlist { diff -urN linux-2.6.2-rc2/include/asm-ia64/siginfo.h linux-2.6.2-rc3/include/asm-ia64/siginfo.h --- linux-2.6.2-rc2/include/asm-ia64/siginfo.h 2004-01-08 23:00:02.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/siginfo.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,10 @@ #define _ASM_IA64_SIGINFO_H /* - * Copyright (C) 1998-2002 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998-2002 + * David Mosberger-Tang , Hewlett-Packard Co */ #define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 4) diff -urN linux-2.6.2-rc2/include/asm-ia64/signal.h linux-2.6.2-rc3/include/asm-ia64/signal.h --- linux-2.6.2-rc2/include/asm-ia64/signal.h 2004-01-08 22:59:09.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/signal.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_SIGNAL_H /* - * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co - * David Mosberger-Tang + * Modified 1998-2001, 2003 + * David Mosberger-Tang , Hewlett-Packard Co * * Unfortunately, this file is being included by bits/signal.h in * glibc-2.x. Hence the #ifdef __KERNEL__ ugliness. diff -urN linux-2.6.2-rc2/include/asm-ia64/socket.h linux-2.6.2-rc3/include/asm-ia64/socket.h --- linux-2.6.2-rc2/include/asm-ia64/socket.h 2004-01-30 18:49:16.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/socket.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,10 +2,12 @@ #define _ASM_IA64_SOCKET_H /* - * Socket related defines. This mostly mirrors the Linux/x86 version. + * Socket related defines. * - * Copyright (C) 1998-2000 Hewlett-Packard Co - * Copyright (C) 1998-2000 David Mosberger-Tang + * Based on . + * + * Modified 1998-2000 + * David Mosberger-Tang , Hewlett-Packard Co */ #include diff -urN linux-2.6.2-rc2/include/asm-ia64/sockios.h linux-2.6.2-rc3/include/asm-ia64/sockios.h --- linux-2.6.2-rc2/include/asm-ia64/sockios.h 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/sockios.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,11 +2,12 @@ #define _ASM_IA64_SOCKIOS_H /* - * Socket-level I/O control calls. This mostly mirrors the Linux/x86 - * version. + * Socket-level I/O control calls. * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Based on . + * + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co */ #define FIOSETOWN 0x8901 #define SIOCSPGRP 0x8902 diff -urN linux-2.6.2-rc2/include/asm-ia64/stat.h linux-2.6.2-rc3/include/asm-ia64/stat.h --- linux-2.6.2-rc2/include/asm-ia64/stat.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/stat.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_STAT_H /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co */ struct stat { diff -urN linux-2.6.2-rc2/include/asm-ia64/statfs.h linux-2.6.2-rc3/include/asm-ia64/statfs.h --- linux-2.6.2-rc2/include/asm-ia64/statfs.h 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/statfs.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,10 @@ #define _ASM_IA64_STATFS_H /* - * Copyright (C) 1998, 1999, 2003 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998, 1999, 2003 + * David Mosberger-Tang , Hewlett-Packard Co */ #ifndef __KERNEL_STRICT_NAMES diff -urN linux-2.6.2-rc2/include/asm-ia64/termbits.h linux-2.6.2-rc3/include/asm-ia64/termbits.h --- linux-2.6.2-rc2/include/asm-ia64/termbits.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/termbits.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,10 @@ #define _ASM_IA64_TERMBITS_H /* - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang + * Based on . + * + * Modified 1999 + * David Mosberger-Tang , Hewlett-Packard Co * * 99/01/28 Added new baudrates */ diff -urN linux-2.6.2-rc2/include/asm-ia64/termios.h linux-2.6.2-rc3/include/asm-ia64/termios.h --- linux-2.6.2-rc2/include/asm-ia64/termios.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/termios.h 2004-01-30 18:49:24.000000000 -0800 @@ -2,8 +2,8 @@ #define _ASM_IA64_TERMIOS_H /* - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang + * Modified 1999 + * David Mosberger-Tang , Hewlett-Packard Co * * 99/01/28 Added N_IRDA and N_SMSBLOCK */ diff -urN linux-2.6.2-rc2/include/asm-ia64/tlb.h linux-2.6.2-rc3/include/asm-ia64/tlb.h --- linux-2.6.2-rc2/include/asm-ia64/tlb.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/tlb.h 2004-01-30 18:49:24.000000000 -0800 @@ -1,10 +1,10 @@ #ifndef _ASM_IA64_TLB_H #define _ASM_IA64_TLB_H /* + * Based on . + * * Copyright (C) 2002-2003 Hewlett-Packard Co * David Mosberger-Tang - * - * This file was derived from asm-generic/tlb.h. */ /* * Removing a translation from a page table (including TLB-shootdown) is a four-step diff -urN linux-2.6.2-rc2/include/asm-ia64/types.h linux-2.6.2-rc3/include/asm-ia64/types.h --- linux-2.6.2-rc2/include/asm-ia64/types.h 2004-01-08 22:59:10.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/types.h 2004-01-30 18:49:24.000000000 -0800 @@ -7,8 +7,10 @@ * space pollution is not a major issue. However, for interoperability, libraries still * need to be careful to avoid a name clashes. * - * Copyright (C) 1998-2000, 2002 Hewlett-Packard Co - * David Mosberger-Tang + * Based on . + * + * Modified 1998-2000, 2002 + * David Mosberger-Tang , Hewlett-Packard Co */ #ifdef __ASSEMBLY__ diff -urN linux-2.6.2-rc2/include/asm-ia64/uaccess.h linux-2.6.2-rc3/include/asm-ia64/uaccess.h --- linux-2.6.2-rc2/include/asm-ia64/uaccess.h 2004-01-30 18:49:16.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/uaccess.h 2004-01-30 18:49:24.000000000 -0800 @@ -26,7 +26,9 @@ * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and * then resumes execution at the continuation point. * - * Copyright (C) 1998, 1999, 2001-2003 Hewlett-Packard Co + * Based on . + * + * Copyright (C) 1998, 1999, 2001-2004 Hewlett-Packard Co * David Mosberger-Tang */ @@ -281,24 +283,23 @@ __su_ret; \ }) +/* Generic code can't deal with the location-relative format that we use for compactness. */ #define ARCH_HAS_SORT_EXTABLE #define ARCH_HAS_SEARCH_EXTABLE struct exception_table_entry { - int addr; /* gp-relative address of insn this fixup is for */ - int cont; /* gp-relative continuation address; if bit 2 is set, r9 is set to 0 */ + int addr; /* location-relative address of insn this fixup is for */ + int cont; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */ }; extern void handle_exception (struct pt_regs *regs, const struct exception_table_entry *e); extern const struct exception_table_entry *search_exception_tables (unsigned long addr); -# define SEARCH_EXCEPTION_TABLE(regs) search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri) - static inline int done_with_exception (struct pt_regs *regs) { const struct exception_table_entry *e; - e = SEARCH_EXCEPTION_TABLE(regs); + e = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); if (e) { handle_exception(regs, e); return 1; diff -urN linux-2.6.2-rc2/include/asm-ia64/unaligned.h linux-2.6.2-rc3/include/asm-ia64/unaligned.h --- linux-2.6.2-rc2/include/asm-ia64/unaligned.h 2004-01-08 23:00:03.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/unaligned.h 2004-01-30 18:49:24.000000000 -0800 @@ -4,8 +4,9 @@ #include /* - * The main single-value unaligned transfer routines. Derived from - * the Linux/Alpha version. + * The main single-value unaligned transfer routines. + * + * Based on . * * Copyright (C) 1998, 1999, 2003 Hewlett-Packard Co * David Mosberger-Tang diff -urN linux-2.6.2-rc2/include/asm-ia64/user.h linux-2.6.2-rc3/include/asm-ia64/user.h --- linux-2.6.2-rc2/include/asm-ia64/user.h 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-ia64/user.h 2004-01-30 18:49:24.000000000 -0800 @@ -24,8 +24,8 @@ * current->start_stack, so we round each of these in order to be able * to write an integer number of pages. * - * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co - * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang + * Modified 1998, 1999, 2001 + * David Mosberger-Tang , Hewlett-Packard Co */ #include diff -urN linux-2.6.2-rc2/include/asm-sparc64/io.h linux-2.6.2-rc3/include/asm-sparc64/io.h --- linux-2.6.2-rc2/include/asm-sparc64/io.h 2004-01-08 22:59:56.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-sparc64/io.h 2004-01-30 18:49:24.000000000 -0800 @@ -19,7 +19,7 @@ #define bus_to_virt bus_to_virt_not_defined_use_pci_map /* BIO layer definitions. */ -extern unsigned long phys_base; +extern unsigned long phys_base, kern_base, kern_size; #define page_to_phys(page) ((((page) - mem_map) << PAGE_SHIFT)+phys_base) #define BIO_VMERGE_BOUNDARY 8192 diff -urN linux-2.6.2-rc2/include/asm-sparc64/sections.h linux-2.6.2-rc3/include/asm-sparc64/sections.h --- linux-2.6.2-rc2/include/asm-sparc64/sections.h 2004-01-08 22:59:18.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-sparc64/sections.h 2004-01-30 18:49:24.000000000 -0800 @@ -4,4 +4,6 @@ /* nothing to see, move along */ #include +extern char _end[], _start[]; + #endif diff -urN linux-2.6.2-rc2/include/asm-x86_64/acpi.h linux-2.6.2-rc3/include/asm-x86_64/acpi.h --- linux-2.6.2-rc2/include/asm-x86_64/acpi.h 2004-01-08 22:59:45.000000000 -0800 +++ linux-2.6.2-rc3/include/asm-x86_64/acpi.h 2004-01-30 18:49:24.000000000 -0800 @@ -100,25 +100,26 @@ :"0"(n_hi), "1"(n_lo)) -#ifndef CONFIG_ACPI_BOOT -#define acpi_lapic 0 -#define acpi_ioapic 0 -#else -#ifdef CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_ACPI_BOOT extern int acpi_lapic; -#else -#define acpi_lapic 0 -#endif -#ifdef CONFIG_X86_IO_APIC extern int acpi_ioapic; -#else -#define acpi_ioapic 0 -#endif +extern int acpi_noirq; /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ #define FIX_ACPI_PAGES 4 -#endif /*CONFIG_ACPI_BOOT*/ +#else /* !CONFIG_ACPI_BOOT */ +#define acpi_lapic 0 +#define acpi_ioapic 0 +#endif /* !CONFIG_ACPI_BOOT */ + +#ifdef CONFIG_ACPI_PCI +static inline void acpi_noirq_set(void) { acpi_noirq = 1; } +extern int acpi_irq_balance_set(char *str); +#else +static inline void acpi_noirq_set(void) { } +static inline int acpi_irq_balance_set(char *str) { return 0; } +#endif #ifdef CONFIG_ACPI_SLEEP diff -urN linux-2.6.2-rc2/include/linux/pci.h linux-2.6.2-rc3/include/linux/pci.h --- linux-2.6.2-rc2/include/linux/pci.h 2004-01-08 22:59:33.000000000 -0800 +++ linux-2.6.2-rc3/include/linux/pci.h 2004-01-30 18:49:24.000000000 -0800 @@ -425,8 +425,8 @@ unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int multifunction:1;/* Part of multi-function device */ #ifdef CONFIG_PCI_NAMES -#define PCI_NAME_SIZE 50 -#define PCI_NAME_HALF __stringify(20) /* less than half to handle slop */ +#define PCI_NAME_SIZE 96 +#define PCI_NAME_HALF __stringify(43) /* less than half to handle slop */ char pretty_name[PCI_NAME_SIZE]; /* pretty name for users to see */ #endif }; @@ -473,10 +473,12 @@ char name[48]; - struct device * dev; + struct device *bridge; + struct class_device class_dev; }; -#define pci_bus_b(n) list_entry(n, struct pci_bus, node) +#define pci_bus_b(n) list_entry(n, struct pci_bus, node) +#define to_pci_bus(n) container_of(n, struct pci_bus, class_dev) /* * Error values that may be returned by PCI functions. @@ -585,6 +587,7 @@ return pci_scan_bus_parented(NULL, bus, ops, sysdata); } int pci_scan_slot(struct pci_bus *bus, int devfn); +struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn); void pci_bus_add_devices(struct pci_bus *bus); void pci_name_device(struct pci_dev *dev); char *pci_class_name(u32 class); @@ -612,6 +615,8 @@ struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); +struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); + int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val); int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val); int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val); @@ -785,26 +790,7 @@ { int rc = pci_register_driver (drv); - if (rc > 0) - return 0; - - /* iff CONFIG_HOTPLUG and built into kernel, we should - * leave the driver around for future hotplug events. - * For the module case, a hotplug daemon of some sort - * should load a module in response to an insert event. */ -#if defined(CONFIG_HOTPLUG) && !defined(MODULE) - if (rc == 0) - return 0; -#else - if (rc == 0) - rc = -ENODEV; -#endif - - /* if we get here, we need to clean up pci driver instance - * and return some sort of error */ - pci_unregister_driver (drv); - - return rc; + return rc < 0 ? rc : 0; } /* diff -urN linux-2.6.2-rc2/include/linux/usb.h linux-2.6.2-rc3/include/linux/usb.h --- linux-2.6.2-rc2/include/linux/usb.h 2004-01-08 22:59:26.000000000 -0800 +++ linux-2.6.2-rc3/include/linux/usb.h 2004-01-30 18:49:24.000000000 -0800 @@ -856,7 +856,6 @@ /* wrappers around usb_control_msg() for the most common standard requests */ extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size); -extern int usb_get_device_descriptor(struct usb_device *dev); extern int usb_get_status(struct usb_device *dev, int type, int target, void *data); extern int usb_get_string(struct usb_device *dev, diff -urN linux-2.6.2-rc2/init/main.c linux-2.6.2-rc3/init/main.c --- linux-2.6.2-rc2/init/main.c 2004-01-30 18:49:16.000000000 -0800 +++ linux-2.6.2-rc3/init/main.c 2004-01-30 18:49:24.000000000 -0800 @@ -409,6 +409,7 @@ parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param, &unknown_bootoption); + sort_main_extable(); trap_init(); rcu_init(); init_IRQ(); @@ -436,7 +437,6 @@ page_address_init(); mem_init(); kmem_cache_init(); - sort_main_extable(); if (late_time_init) late_time_init(); calibrate_delay(); diff -urN linux-2.6.2-rc2/ipc/msg.c linux-2.6.2-rc3/ipc/msg.c --- linux-2.6.2-rc2/ipc/msg.c 2004-01-08 22:59:03.000000000 -0800 +++ linux-2.6.2-rc3/ipc/msg.c 2004-01-30 18:49:24.000000000 -0800 @@ -557,6 +557,7 @@ switch (cmd) { case IPC_SET: { + err = -EPERM; if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE)) goto out_unlock_up; diff -urN linux-2.6.2-rc2/kernel/power/pmdisk.c linux-2.6.2-rc3/kernel/power/pmdisk.c --- linux-2.6.2-rc2/kernel/power/pmdisk.c 2004-01-08 22:59:43.000000000 -0800 +++ linux-2.6.2-rc3/kernel/power/pmdisk.c 2004-01-30 18:49:24.000000000 -0800 @@ -28,6 +28,7 @@ #include #include #include +#include #include diff -urN linux-2.6.2-rc2/kernel/sched.c linux-2.6.2-rc3/kernel/sched.c --- linux-2.6.2-rc2/kernel/sched.c 2004-01-30 18:49:16.000000000 -0800 +++ linux-2.6.2-rc3/kernel/sched.c 2004-01-30 18:49:24.000000000 -0800 @@ -2856,7 +2856,6 @@ #endif -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) /* * The 'big kernel lock' * @@ -2866,11 +2865,11 @@ * been migrated to a proper locking design yet. * * Don't use in new code. + * + * Note: spinlock debugging needs this even on !CONFIG_SMP. */ spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; - EXPORT_SYMBOL(kernel_flag); -#endif static void kstat_init_cpu(int cpu) { diff -urN linux-2.6.2-rc2/net/ipv6/tcp_ipv6.c linux-2.6.2-rc3/net/ipv6/tcp_ipv6.c --- linux-2.6.2-rc2/net/ipv6/tcp_ipv6.c 2004-01-08 22:59:44.000000000 -0800 +++ linux-2.6.2-rc3/net/ipv6/tcp_ipv6.c 2004-01-30 18:49:24.000000000 -0800 @@ -485,7 +485,7 @@ unique: BUG_TRAP(sk_unhashed(sk)); - sk_add_node(sk, &head->chain); + __sk_add_node(sk, &head->chain); sk->sk_hashent = hash; sock_prot_inc_use(sk->sk_prot); write_unlock_bh(&head->lock); diff -urN linux-2.6.2-rc2/sound/usb/usbaudio.c linux-2.6.2-rc3/sound/usb/usbaudio.c --- linux-2.6.2-rc2/sound/usb/usbaudio.c 2004-01-08 22:59:48.000000000 -0800 +++ linux-2.6.2-rc3/sound/usb/usbaudio.c 2004-01-30 18:49:24.000000000 -0800 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -2560,9 +2561,10 @@ err = usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ); if (err < 0) snd_printdd("error sending boot message: %d\n", err); - err = usb_get_device_descriptor(dev); + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); config = dev->actconfig; - if (err < 0) snd_printdd("error usb_get_device_descriptor: %d\n", err); + if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err); err = usb_reset_configuration(dev); if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err); snd_printdd("extigy_boot: new boot length = %d\n", get_cfg_desc(config)->wTotalLength);