From: Marc Fiuczynski Date: Thu, 19 Oct 2006 02:13:07 +0000 (+0000) Subject: Merge to Fedora kernel-2.6.17-1.2187_FC5 patched with stable patch-2.6.17.13-vs2... X-Git-Tag: fedora-2_6_17-1_2187_FC5-vs2_0_2_1~1 X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=commitdiff_plain;h=4e76c8a9fa413ccc09d3f7f664183dcce3555d57 Merge to Fedora kernel-2.6.17-1.2187_FC5 patched with stable patch-2.6.17.13-vs2.0.2.1.diff --- diff --git a/.config b/.config index de7e3e791..409409530 100644 --- a/.config +++ b/.config @@ -1,40 +1,61 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.17.13 +# Wed Oct 18 17:15:54 2006 # +CONFIG_X86_32=y +CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_X86=y CONFIG_MMU=y -CONFIG_UID16=y CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=17 -CONFIG_HOTPLUG=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y # CONFIG_IKCONFIG is not set +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_VM86=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=m # # Loadable module support @@ -42,24 +63,46 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set CONFIG_KMOD=y -CONFIG_STOP_MACHINE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" # # Processor type and features # -# CONFIG_X86_PC is not set +# CONFIG_SMP is not set +CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_NUMAQ is not set # CONFIG_X86_SUMMIT is not set # CONFIG_X86_BIGSMP is not set # CONFIG_X86_VISWS is not set -CONFIG_X86_GENERICARCH=y +# CONFIG_X86_GENERICARCH is not set # CONFIG_X86_ES7000 is not set -CONFIG_X86_CYCLONE_TIMER=y # CONFIG_M386 is not set # CONFIG_M486 is not set # CONFIG_M586 is not set @@ -74,9 +117,12 @@ CONFIG_M686=y # CONFIG_MK7 is not set # CONFIG_MK8 is not set # CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set # CONFIG_MWINCHIPC6 is not set # CONFIG_MWINCHIP2 is not set # CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set # CONFIG_MCYRIXIII is not set # CONFIG_MVIAC3_2 is not set CONFIG_X86_GENERIC=y @@ -84,85 +130,111 @@ CONFIG_X86_CMPXCHG=y CONFIG_X86_XADD=y CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_X86_PPRO_FENCE=y CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_INVLPG=y CONFIG_X86_BSWAP=y CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y CONFIG_X86_GOOD_APIC=y CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_4G=y -CONFIG_X86_SWITCH_PAGETABLES=y -CONFIG_X86_4G_VM_LAYOUT=y -CONFIG_X86_UACCESS_INDIRECT=y -CONFIG_X86_HIGH_ENTRY=y +CONFIG_X86_TSC=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y -CONFIG_SMP=y -CONFIG_NR_CPUS=32 -CONFIG_SCHED_SMT=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set +CONFIG_X86_UP_APIC=y +CONFIG_X86_UP_IOAPIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y -CONFIG_X86_TSC=y CONFIG_X86_MCE=y # CONFIG_X86_MCE_NONFATAL is not set CONFIG_X86_MCE_P4THERMAL=y CONFIG_TOSHIBA=m CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set CONFIG_MICROCODE=m CONFIG_X86_MSR=m CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set # # Firmware Drivers # CONFIG_EDD=m +CONFIG_EFI_VARS=y +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m # CONFIG_NOHIGHMEM is not set -# CONFIG_HIGHMEM4G is not set -CONFIG_HIGHMEM64G=y +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_HIGHMEM=y -CONFIG_X86_PAE=y -# CONFIG_NUMA is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_HIGHPTE=y # CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y -# CONFIG_EFI is not set -# CONFIG_IRQBALANCE is not set -CONFIG_HAVE_DEC_LOCK=y +CONFIG_EFI=y +CONFIG_BOOT_IOREMAP=y CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # # Power management options (ACPI, APM) # CONFIG_PM=y -# CONFIG_SOFTWARE_SUSPEND is not set -# CONFIG_PM_DISK is not set +CONFIG_PM_LEGACY=y +CONFIG_PM_DEBUG=y +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" # # ACPI (Advanced Configuration and Power Interface) Support # CONFIG_ACPI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_SLEEP=y CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set CONFIG_ACPI_AC=m CONFIG_ACPI_BATTERY=m CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set CONFIG_ACPI_FAN=y CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_THERMAL=y CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_IBM_DOCK=y CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=1999 # CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_BUS=y CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y CONFIG_X86_PM_TIMER=y +# CONFIG_ACPI_CONTAINER is not set # # APM (Advanced Power Management) BIOS Support @@ -180,34 +252,43 @@ CONFIG_APM_RTC_IS_GMT=y # CPU Frequency scaling # CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=m CONFIG_CPU_FREQ_GOV_USERSPACE=y -# CONFIG_CPU_FREQ_24_API is not set -CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m # # CPUFreq processor drivers # CONFIG_X86_ACPI_CPUFREQ=m -# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set -CONFIG_X86_POWERNOW_K6=m +# CONFIG_X86_POWERNOW_K6 is not set CONFIG_X86_POWERNOW_K7=y -CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y # CONFIG_X86_GX_SUSPMOD is not set CONFIG_X86_SPEEDSTEP_CENTRINO=y -CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y CONFIG_X86_SPEEDSTEP_ICH=y -CONFIG_X86_SPEEDSTEP_SMI=m +CONFIG_X86_SPEEDSTEP_SMI=y CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set CONFIG_X86_SPEEDSTEP_LIB=y # CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set -CONFIG_X86_LONGRUN=y -# CONFIG_X86_LONGHAUL is not set # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) @@ -216,810 +297,1029 @@ CONFIG_PCI=y # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GOMMCONFIG is not set # CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y -CONFIG_PCI_USE_VECTOR=y -CONFIG_PCI_LEGACY_PROC=y -# CONFIG_PCI_NAMES is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y CONFIG_ISA=y # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SCx200 is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set -CONFIG_YENTA=m +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m CONFIG_I82092=m -CONFIG_I82365=m -CONFIG_TCIC=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y # # PCI Hotplug Support # CONFIG_HOTPLUG_PCI=y -# CONFIG_HOTPLUG_PCI_FAKE is not set +CONFIG_HOTPLUG_PCI_FAKE=m CONFIG_HOTPLUG_PCI_COMPAQ=m # CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_ACPI is not set +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m # CONFIG_HOTPLUG_PCI_CPCI is not set -CONFIG_HOTPLUG_PCI_PCIE=m -CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE=y -CONFIG_HOTPLUG_PCI_SHPC=m -CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y +# CONFIG_HOTPLUG_PCI_SHPC is not set # # Executable file formats # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_MISC=y # -# Device Drivers +# Networking # +CONFIG_NET=y # -# Generic Driver Options +# Networking options # -CONFIG_FW_LOADER=y -# CONFIG_DEBUG_DRIVER is not set +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y # -# Memory Technology Devices (MTD) +# IP: Virtual Server Configuration # -CONFIG_MTD=m -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=m -CONFIG_MTD_CONCAT=m -CONFIG_MTD_REDBOOT_PARTS=m -CONFIG_MTD_CMDLINE_PARTS=m +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 # -# User Modules And Translation Layers +# IPVS transport protocol load balancing support # -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=m -CONFIG_MTD_BLOCK_RO=m -CONFIG_FTL=m -CONFIG_NFTL=m -CONFIG_NFTL_RW=y -CONFIG_INFTL=m +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y # -# RAM/ROM/Flash chip drivers +# IPVS scheduler # -CONFIG_MTD_CFI=m -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=m -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_INTELEXT=m -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_STAA=m -CONFIG_MTD_RAM=m -CONFIG_MTD_ROM=m -CONFIG_MTD_ABSENT=m -# CONFIG_MTD_OBSOLETE_CHIPS is not set +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m # -# Mapping drivers for chip access +# IPVS application helper # -CONFIG_MTD_COMPLEX_MAPPINGS=y -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PNC2000 is not set -CONFIG_MTD_SC520CDP=m -CONFIG_MTD_NETSC520=m -CONFIG_MTD_SBC_GXX=m -CONFIG_MTD_ELAN_104NC=m -CONFIG_MTD_SCx200_DOCFLASH=m -CONFIG_MTD_AMD76XROM=m -CONFIG_MTD_ICH2ROM=m -CONFIG_MTD_SCB2_FLASH=m -# CONFIG_MTD_NETtel is not set -# CONFIG_MTD_DILNETPC is not set -CONFIG_MTD_L440GX=m -CONFIG_MTD_PCI=m +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y # -# Self-contained MTD device drivers +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + # -CONFIG_MTD_PMC551=m -# CONFIG_MTD_PMC551_BUGFIX is not set -# CONFIG_MTD_PMC551_DEBUG is not set -# CONFIG_MTD_SLRAM is not set -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -# CONFIG_MTD_BLKMTD is not set +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m # -# Disk-On-Chip Device Drivers +# IPv6: Netfilter Configuration (EXPERIMENTAL) # -CONFIG_MTD_DOC2000=m -# CONFIG_MTD_DOC2001 is not set -CONFIG_MTD_DOC2001PLUS=m -CONFIG_MTD_DOCPROBE=m -# CONFIG_MTD_DOCPROBE_ADVANCED is not set -CONFIG_MTD_DOCPROBE_ADDRESS=0 +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m # -# NAND Flash Device Drivers +# DECnet: Netfilter Configuration # -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_IDS=m +# CONFIG_DECNET_NF_GRABULATOR is not set # -# Parallel port support +# Bridge: Netfilter Configuration # -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m # -# Plug and Play support +# DCCP Configuration (EXPERIMENTAL) # -CONFIG_PNP=y -# CONFIG_PNP_DEBUG is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y # -# Protocols +# DCCP CCIDs Configuration (EXPERIMENTAL) # -CONFIG_ISAPNP=y -# CONFIG_PNPBIOS is not set +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m # -# Block devices +# DCCP Kernel Hacking # -CONFIG_BLK_DEV_FD=m -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -CONFIG_BLK_CPQ_DA=m -CONFIG_BLK_CPQ_CISS_DA=m -CONFIG_CISS_SCSI_TAPE=y -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_CARMEL=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=16384 -CONFIG_BLK_DEV_INITRD=y -CONFIG_LBD=y +# CONFIG_IP_DCCP_DEBUG is not set # -# ATA/ATAPI/MFM/RLL support +# SCTP Configuration (EXPERIMENTAL) # -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y # -# Please see Documentation/ide.txt for help/info on IDE drives +# TIPC Configuration (EXPERIMENTAL) # -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=y +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +CONFIG_NET_DIVERT=y +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m # -# IDE chipset support/bugfixes +# QoS and/or fair queueing # -CONFIG_IDE_GENERIC=y -# CONFIG_BLK_DEV_CMD640 is not set -CONFIG_BLK_DEV_IDEPNP=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -# CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_BLK_DEV_GENERIC=y -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_RZ1000=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -CONFIG_BLK_DEV_ATIIXP=y -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5520=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_ARM is not set -# CONFIG_IDE_CHIPSETS is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_BLK_DEV_HD is not set +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set # -# SCSI device support +# Queueing/Scheduling # -CONFIG_SCSI=m -CONFIG_SCSI_PROC_FS=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m # -# SCSI support type (disk, tape, CD-ROM) +# Classification # -CONFIG_BLK_DEV_SD=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=m +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y # -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# Network testing # -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m # -# SCSI Transport Attributes +# IrDA protocols # -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set # -# SCSI low-level drivers +# IrDA options # -CONFIG_BLK_DEV_3W_XXXX_RAID=m -# CONFIG_SCSI_7000FASST is not set -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=4 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -# CONFIG_SCSI_DPT_I2O is not set -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -CONFIG_SCSI_IPS=m -CONFIG_SCSI_INIA100=m -CONFIG_SCSI_PPA=m -CONFIG_SCSI_IMM=m -# CONFIG_SCSI_IZIP_EPP16 is not set -# CONFIG_SCSI_IZIP_SLOW_CTR is not set -# CONFIG_SCSI_NCR53C406A is not set -CONFIG_SCSI_SYM53C8XX_2=m -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PSI240I is not set -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -# CONFIG_SCSI_QLOGIC_FC is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_QLA2XXX=m -CONFIG_SCSI_QLA21XX=m -CONFIG_SCSI_QLA22XX=m -CONFIG_SCSI_QLA2300=m -CONFIG_SCSI_QLA2322=m -CONFIG_SCSI_QLA6312=m -CONFIG_SCSI_QLA6322=m -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC395x is not set -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set # -# PCMCIA SCSI adapter support +# Infrared-port device drivers # -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m -CONFIG_PCMCIA_SYM53C500=m # -# Old CD-ROM drivers (not SCSI, not IDE) +# SIR device drivers # -# CONFIG_CD_NO_IDESCSI is not set +CONFIG_IRTTY_SIR=m # -# Multi-device support (RAID and LVM) +# Dongle support # -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_RAID6=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_DM=m -CONFIG_DM_CRYPT=m +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m # -# Fusion MPT device support +# Old SIR device drivers # -CONFIG_FUSION=m -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m +CONFIG_IRPORT_SIR=m # -# IEEE 1394 (FireWire) support +# Old Serial dongle support # -CONFIG_IEEE1394=m +# CONFIG_DONGLE_OLD is not set # -# Subsystem Options +# FIR device drivers # -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -CONFIG_IEEE1394_OUI_DB=y -# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m # -# Device Drivers +# Bluetooth device drivers # -# CONFIG_IEEE1394_PCILYNX is not set -CONFIG_IEEE1394_OHCI1394=m +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m # -# Protocol Drivers +# TUX options # -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set -# CONFIG_IEEE1394_ETH1394 is not set -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y # -# I2O device support +# Device Drivers # -CONFIG_I2O=m -CONFIG_I2O_CONFIG=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m # -# Networking support +# Generic Driver Options # -CONFIG_NET=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set # -# Networking options +# Connector - unified userspace <-> kernelspace linker # -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m +CONFIG_CONNECTOR=m # -# IP: Virtual Server Configuration +# Memory Technology Devices (MTD) # -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y # -# IPVS transport protocol load balancing support +# User Modules And Translation Layers # -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m # -# IPVS scheduler +# RAM/ROM/Flash chip drivers # -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -CONFIG_IP_VS_SED=m -CONFIG_IP_VS_NQ=m +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set # -# IPVS application helper +# Mapping drivers for chip access # -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set # -# IP: Netfilter Configuration +# Self-contained MTD device drivers # -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_MATCH_PHYSDEV=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m # -# IPv6: Netfilter Configuration +# Disk-On-Chip Device Drivers # -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IP6_NF_RAW=m +CONFIG_MTD_DOC2000=m +# CONFIG_MTD_DOC2001 is not set +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y +# CONFIG_PNPBIOS is not set +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# 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_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +CONFIG_BLK_DEV_CY82C693=y +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +CONFIG_BLK_DEV_SLC90E66=y +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set # -# Bridge: Netfilter Configuration +# SCSI device support # -CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m -CONFIG_BRIDGE_EBT_802_3=m -CONFIG_BRIDGE_EBT_AMONG=m -CONFIG_BRIDGE_EBT_ARP=m -CONFIG_BRIDGE_EBT_IP=m -CONFIG_BRIDGE_EBT_LIMIT=m -CONFIG_BRIDGE_EBT_MARK=m -CONFIG_BRIDGE_EBT_PKTTYPE=m -CONFIG_BRIDGE_EBT_STP=m -CONFIG_BRIDGE_EBT_VLAN=m -CONFIG_BRIDGE_EBT_ARPREPLY=m -CONFIG_BRIDGE_EBT_DNAT=m -CONFIG_BRIDGE_EBT_MARK_T=m -CONFIG_BRIDGE_EBT_REDIRECT=m -CONFIG_BRIDGE_EBT_SNAT=m -CONFIG_BRIDGE_EBT_LOG=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y # -# SCTP Configuration (EXPERIMENTAL) +# SCSI support type (disk, tape, CD-ROM) # -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -# CONFIG_ATM is not set -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -# CONFIG_DECNET is not set -CONFIG_LLC=m -# CONFIG_LLC2 is not set -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m # -# QoS and/or fair queueing +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_DELAY=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y # -# Network testing +# SCSI Transport Attributes # -# CONFIG_NET_PKTGEN is not set -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y -# CONFIG_HAMRADIO is not set -CONFIG_IRDA=m +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m # -# IrDA protocols +# SCSI low-level drivers # -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -# CONFIG_IRDA_ULTRA is not set +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y +CONFIG_SCSI_QLA21XX=m +CONFIG_SCSI_QLA22XX=m +CONFIG_SCSI_QLA2300=m +CONFIG_SCSI_QLA2322=m +CONFIG_SCSI_QLA24XX=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set # -# IrDA options +# PCMCIA SCSI adapter support # -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m # -# Infrared-port device drivers +# Old CD-ROM drivers (not SCSI, not IDE) # +# CONFIG_CD_NO_IDESCSI is not set # -# SIR device drivers +# Multi-device support (RAID and LVM) # -CONFIG_IRTTY_SIR=m +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID5=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_RAID6=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m # -# Dongle support +# Fusion MPT device support # -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m # -# Old SIR device drivers +# IEEE 1394 (FireWire) support # +CONFIG_IEEE1394=m # -# Old Serial dongle support +# Subsystem Options # +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set # -# FIR device drivers +# Device Drivers # -CONFIG_USB_IRDA=m -CONFIG_SIGMATEL_FIR=m -CONFIG_NSC_FIR=m -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -# CONFIG_VIA_FIR is not set -CONFIG_BT=m -CONFIG_BT_L2CAP=m -CONFIG_BT_SCO=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_CMTP=m +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m # -# Bluetooth device drivers +# Protocol Drivers # -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_BCSP_TXCRC=y -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_BT_HCIDTL1=m -CONFIG_BT_HCIBT3C=m -CONFIG_BT_HCIBLUECARD=m -CONFIG_BT_HCIBTUART=m -CONFIG_BT_HCIVHCI=m -CONFIG_TUX=m +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m # -# TUX options +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support # -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_EQUALIZER=m CONFIG_TUN=m -CONFIG_ETHERTAP=m CONFIG_NET_SB1000=m # @@ -1027,6 +1327,20 @@ CONFIG_NET_SB1000=m # # CONFIG_ARCNET is not set +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m + # # Ethernet (10 or 100Mbit) # @@ -1034,23 +1348,22 @@ CONFIG_NET_ETHERNET=y CONFIG_MII=m CONFIG_HAPPYMEAL=m CONFIG_SUNGEM=m +CONFIG_CASSINI=m CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set CONFIG_EL3=m -CONFIG_3C515=m +# CONFIG_3C515 is not set CONFIG_VORTEX=m CONFIG_TYPHOON=m -CONFIG_LANCE=m +# CONFIG_LANCE is not set CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m +# CONFIG_WD80x3 is not set CONFIG_ULTRA=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI52=m -CONFIG_NI65=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set # # Tulip family network device support @@ -1064,34 +1377,44 @@ CONFIG_TULIP_MMIO=y CONFIG_DE4X5=m CONFIG_WINBOND_840=m CONFIG_DM9102=m +CONFIG_ULI526X=m CONFIG_PCMCIA_XIRCOM=m +# CONFIG_PCMCIA_XIRTULIP is not set # CONFIG_AT1700 is not set -CONFIG_DEPCA=m +# CONFIG_DEPCA is not set CONFIG_HP100=m -# CONFIG_NET_ISA is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set CONFIG_NET_PCI=y CONFIG_PCNET32=m CONFIG_AMD8111_ETH=m CONFIG_AMD8111E_NAPI=y CONFIG_ADAPTEC_STARFIRE=m CONFIG_ADAPTEC_STARFIRE_NAPI=y -CONFIG_AC3200=m -CONFIG_APRICOT=m +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set CONFIG_B44=m CONFIG_FORCEDETH=m -CONFIG_CS89x0=m +# CONFIG_CS89x0 is not set CONFIG_DGRS=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set +# CONFIG_EEPRO100 is not set CONFIG_E100=m -CONFIG_E100_NAPI=y CONFIG_FEALNX=m CONFIG_NATSEMI=m CONFIG_NE2K_PCI=m CONFIG_8139CP=m CONFIG_8139TOO=m -CONFIG_8139TOO_PIO=y +# CONFIG_8139TOO_PIO is not set # CONFIG_8139TOO_TUNE_TWISTER is not set CONFIG_8139TOO_8129=y # CONFIG_8139_OLD_RX_RESET is not set @@ -1108,20 +1431,32 @@ CONFIG_DE600=m CONFIG_DE620=m # -# Gigabit Ethernet (1000/10000 Mbit) +# Ethernet (1000 Mbit) # -CONFIG_NET_GIGE=y CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set CONFIG_DL2K=m CONFIG_E1000=m CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m -CONFIG_SK98LIN=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m CONFIG_IXGB=m CONFIG_IXGB_NAPI=y CONFIG_S2IO=m @@ -1130,19 +1465,26 @@ CONFIG_S2IO_NAPI=y # # Token Ring devices # -# CONFIG_TR is not set +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set # # Wireless LAN (non-hamradio) # CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y # # Obsolete Wireless cards support (pre-802.11) # # CONFIG_STRIP is not set # CONFIG_ARLAN is not set -CONFIG_WAVELAN=m +# CONFIG_WAVELAN is not set CONFIG_PCMCIA_WAVELAN=m CONFIG_PCMCIA_NETWAVE=m @@ -1154,10 +1496,18 @@ CONFIG_PCMCIA_NETWAVE=m # # Wireless 802.11b ISA/PCI cards support # +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW_QOS=y +# CONFIG_IPW2200_DEBUG is not set CONFIG_AIRO=m CONFIG_HERMES=m CONFIG_PLX_HERMES=m CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m CONFIG_PCI_HERMES=m CONFIG_ATMEL=m CONFIG_PCI_ATMEL=m @@ -1166,6 +1516,7 @@ CONFIG_PCI_ATMEL=m # Wireless 802.11b Pcmcia/Cardbus cards support # CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m CONFIG_AIRO_CS=m CONFIG_PCMCIA_ATMEL=m CONFIG_PCMCIA_WL3501=m @@ -1174,6 +1525,19 @@ CONFIG_PCMCIA_WL3501=m # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support # CONFIG_PRISM54=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set CONFIG_NET_WIRELESS=y # @@ -1188,11 +1552,40 @@ CONFIG_PCMCIA_NMCLAN=m CONFIG_PCMCIA_SMC91C92=m CONFIG_PCMCIA_XIRC2PS=m CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m # # Wan interfaces # # CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set CONFIG_FDDI=y # CONFIG_DEFXX is not set CONFIG_SKFP=m @@ -1205,11 +1598,20 @@ CONFIG_PPP_ASYNC=m CONFIG_PPP_SYNC_TTY=m CONFIG_PPP_DEFLATE=m # CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m CONFIG_PPPOE=m -# CONFIG_SLIP is not set +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set CONFIG_NET_FC=y # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y # # ISDN subsystem @@ -1231,6 +1633,8 @@ CONFIG_ISDN_TTY_FAX=y # # ISDN feature submodules # +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m # # ISDN4Linux hardware drivers @@ -1256,27 +1660,27 @@ CONFIG_HISAX_MAX_CARDS=8 # # HiSax supported cards # -CONFIG_HISAX_16_0=y +# CONFIG_HISAX_16_0 is not set CONFIG_HISAX_16_3=y CONFIG_HISAX_TELESPCI=y CONFIG_HISAX_S0BOX=y -CONFIG_HISAX_AVM_A1=y +# CONFIG_HISAX_AVM_A1 is not set CONFIG_HISAX_FRITZPCI=y CONFIG_HISAX_AVM_A1_PCMCIA=y CONFIG_HISAX_ELSA=y -CONFIG_HISAX_IX1MICROR2=y +# CONFIG_HISAX_IX1MICROR2 is not set CONFIG_HISAX_DIEHLDIVA=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set CONFIG_HISAX_SEDLBAUER=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set CONFIG_HISAX_NETJET=y CONFIG_HISAX_NETJET_U=y CONFIG_HISAX_NICCY=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set CONFIG_HISAX_BKM_A4T=y CONFIG_HISAX_SCT_QUADRO=y CONFIG_HISAX_GAZEL=y @@ -1298,18 +1702,29 @@ CONFIG_HISAX_TELES_CS=m # HiSax sub driver modules # CONFIG_HISAX_ST5481=m -CONFIG_HISAX_HFCUSB=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m CONFIG_HISAX_FRITZ_PCIPNP=m CONFIG_HISAX_HDLC=y # # Active cards # -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -CONFIG_ISDN_DRV_SC=m -CONFIG_ISDN_DRV_ACT2000=m -CONFIG_ISDN_DRV_TPAM=m +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set # # CAPI subsystem @@ -1330,6 +1745,14 @@ CONFIG_ISDN_CAPI_CAPIDRV=m # Active AVM cards # CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m # # Active Eicon DIVA Server cards @@ -1364,24 +1787,6 @@ CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set -# -# Input I/O drivers -# -CONFIG_GAMEPORT=m -CONFIG_SOUND_GAMEPORT=m -CONFIG_GAMEPORT_NS558=m -CONFIG_GAMEPORT_L4=m -CONFIG_GAMEPORT_EMU10K1=m -CONFIG_GAMEPORT_VORTEX=m -CONFIG_GAMEPORT_FM801=m -CONFIG_GAMEPORT_CS461x=m -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PARKBD is not set -# CONFIG_SERIO_PCIPS2 is not set - # # Input Device Drivers # @@ -1394,10 +1799,9 @@ CONFIG_KEYBOARD_ATKBD=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y CONFIG_MOUSE_SERIAL=m -CONFIG_MOUSE_INPORT=m -CONFIG_MOUSE_ATIXL=y -CONFIG_MOUSE_LOGIBM=m -CONFIG_MOUSE_PC110PAD=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set CONFIG_MOUSE_VSXXXAA=m CONFIG_INPUT_JOYSTICK=y CONFIG_JOYSTICK_ANALOG=m @@ -1419,16 +1823,37 @@ CONFIG_JOYSTICK_MAGELLAN=m CONFIG_JOYSTICK_SPACEORB=m CONFIG_JOYSTICK_SPACEBALL=m CONFIG_JOYSTICK_STINGER=m -CONFIG_JOYSTICK_TWIDDLER=m +CONFIG_JOYSTICK_TWIDJOY=m CONFIG_JOYSTICK_DB9=m CONFIG_JOYSTICK_GAMECON=m CONFIG_JOYSTICK_TURBOGRAFX=m -# CONFIG_INPUT_JOYDUMP is not set +CONFIG_JOYSTICK_JOYDUMP=m CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m CONFIG_INPUT_MISC=y CONFIG_INPUT_PCSPKR=m -# CONFIG_INPUT_UINPUT is not set +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m # # Character devices @@ -1437,33 +1862,50 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set CONFIG_ROCKETPORT=m # CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set CONFIG_SYNCLINK=m CONFIG_SYNCLINKMP=m +# CONFIG_SYNCLINK_GT is not set CONFIG_N_HDLC=m -CONFIG_STALDRV=y +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set # # Serial drivers # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y CONFIG_SERIAL_8250_CS=m -# CONFIG_SERIAL_8250_ACPI is not set -CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y -# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_DETECT_IRQ=y -CONFIG_SERIAL_8250_MULTIPORT=y CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set CONFIG_CRASH=m @@ -1471,7 +1913,6 @@ CONFIG_PRINTER=m CONFIG_LP_CONSOLE=y CONFIG_PPDEV=m CONFIG_TIPAR=m -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -1481,6 +1922,7 @@ CONFIG_IPMI_HANDLER=m CONFIG_IPMI_DEVICE_INTERFACE=m CONFIG_IPMI_SI=m CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m # # Watchdog Cards @@ -1492,30 +1934,33 @@ CONFIG_WATCHDOG=y # Watchdog Device Drivers # CONFIG_SOFT_WATCHDOG=m -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set CONFIG_ALIM1535_WDT=m CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m CONFIG_I8XX_TCO=m -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set +# CONFIG_SC1200_WDT is not set # CONFIG_60XX_WDT is not set -CONFIG_CPU5_WDT=m +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set CONFIG_W83627HF_WDT=m CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set # # ISA-based Watchdog Cards # -CONFIG_PCWATCHDOG=m +# CONFIG_PCWATCHDOG is not set # CONFIG_MIXCOMWD is not set -CONFIG_WDT=m -# CONFIG_WDT_501 is not set +# CONFIG_WDT is not set # # PCI-based Watchdog Cards @@ -1529,7 +1974,7 @@ CONFIG_WDT_501_PCI=y # CONFIG_USBPCWATCHDOG=m CONFIG_HW_RANDOM=m -CONFIG_NVRAM=m +CONFIG_NVRAM=y CONFIG_RTC=y CONFIG_DTLK=m CONFIG_R3964=m @@ -1539,36 +1984,50 @@ CONFIG_SONYPI=m # # Ftape, the floppy tape device driver # +# CONFIG_FTAPE is not set CONFIG_AGP=y CONFIG_AGP_ALI=y CONFIG_AGP_ATI=y CONFIG_AGP_AMD=y CONFIG_AGP_AMD64=y CONFIG_AGP_INTEL=y -CONFIG_AGP_INTEL_MCH=y CONFIG_AGP_NVIDIA=y CONFIG_AGP_SIS=y CONFIG_AGP_SWORKS=y CONFIG_AGP_VIA=y CONFIG_AGP_EFFICEON=y -CONFIG_DRM=y +CONFIG_DRM=m CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m CONFIG_DRM_I810=m CONFIG_DRM_I830=m +CONFIG_DRM_I915=m CONFIG_DRM_MGA=m CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m # # PCMCIA character devices # CONFIG_SYNCLINK_CS=m +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m CONFIG_MWAVE=m +CONFIG_CS5535_GPIO=m # CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set CONFIG_HANGCHECK_TIMER=m +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + # # I2C support # @@ -1580,6 +2039,7 @@ CONFIG_I2C_CHARDEV=m # CONFIG_I2C_ALGOBIT=m CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m # # I2C Hardware Bus support @@ -1588,57 +2048,112 @@ CONFIG_I2C_ALI1535=m CONFIG_I2C_ALI1563=m CONFIG_I2C_ALI15X3=m CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m CONFIG_I2C_AMD8111=m +# CONFIG_I2C_ELEKTOR is not set CONFIG_I2C_I801=m CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m CONFIG_I2C_ISA=m CONFIG_I2C_NFORCE2=m -# CONFIG_I2C_PARPORT is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -CONFIG_I2C_PIIX4=m +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m CONFIG_I2C_PROSAVAGE=m CONFIG_I2C_SAVAGE4=m # CONFIG_SCx200_ACB is not set CONFIG_I2C_SIS5595=m CONFIG_I2C_SIS630=m CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m CONFIG_I2C_VIA=m CONFIG_I2C_VIAPRO=m CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS9490=m +CONFIG_W1_MASTER_DS9490_BRIDGE=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m # -# Hardware Sensors Chip support +# Hardware Monitoring support # -CONFIG_I2C_SENSOR=m +CONFIG_HWMON=m +CONFIG_HWMON_VID=m CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m CONFIG_SENSORS_LM78=m CONFIG_SENSORS_LM80=m CONFIG_SENSORS_LM83=m CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47B397=m CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83792D=m CONFIG_SENSORS_W83L785TS=m CONFIG_SENSORS_W83627HF=m - -# -# Other I2C Chip support -# -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m -CONFIG_SENSORS_RTC8564=m -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -1649,22 +2164,30 @@ CONFIG_IBM_ASM=m # Multimedia devices # CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=m # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set CONFIG_VIDEO_BWQCAM=m CONFIG_VIDEO_CQCAM=m CONFIG_VIDEO_W9966=m CONFIG_VIDEO_CPIA=m CONFIG_VIDEO_CPIA_PP=m CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m CONFIG_VIDEO_SAA5246A=m CONFIG_VIDEO_SAA5249=m CONFIG_TUNER_3036=m @@ -1675,95 +2198,262 @@ CONFIG_VIDEO_ZORAN_DC10=m CONFIG_VIDEO_ZORAN_DC30=m CONFIG_VIDEO_ZORAN_LML33=m CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y CONFIG_VIDEO_MXB=m CONFIG_VIDEO_DPC=m CONFIG_VIDEO_HEXIUM_ORION=m CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_OVCAMCHIP=m + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_EM28XX=m +CONFIG_USB_DSBR=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_ET61X251=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_W9968CF=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m # # Radio Adapters # -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set CONFIG_RADIO_GEMTEK_PCI=m CONFIG_RADIO_MAXIRADIO=m CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set # # Digital Video Broadcasting Devices # -# CONFIG_DVB is not set +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terresterial DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m CONFIG_VIDEO_VIDEOBUF=m CONFIG_VIDEO_TUNER=m CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m # # Graphics support # CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_FIRMWARE_EDID is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set # CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set CONFIG_FB_VGA16=m CONFIG_FB_VESA=y CONFIG_VIDEO_SELECT=y -CONFIG_FB_HGA=m -CONFIG_FB_HGA_ACCEL=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set CONFIG_FB_I810=m CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set CONFIG_FB_MATROX=m CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_G=y CONFIG_FB_MATROX_I2C=m CONFIG_FB_MATROX_MAVEN=m CONFIG_FB_MATROX_MULTIHEAD=y -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=m CONFIG_FB_RADEON_I2C=y # CONFIG_FB_RADEON_DEBUG is not set CONFIG_FB_ATY128=m CONFIG_FB_ATY=m CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y CONFIG_FB_ATY_GX=y -# CONFIG_FB_ATY_XL_INIT is not set +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y # CONFIG_FB_SIS is not set CONFIG_FB_NEOMAGIC=m CONFIG_FB_KYRO=m CONFIG_FB_3DFX=m CONFIG_FB_3DFX_ACCEL=y CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m CONFIG_FB_TRIDENT=m CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # CONFIG_VGA_CONSOLE=y -CONFIG_MDA_CONSOLE=m +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_PCI_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y @@ -1775,6 +2465,11 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y # # Sound @@ -1794,8 +2489,13 @@ CONFIG_SND_SEQ_DUMMY=m CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1806,6 +2506,8 @@ CONFIG_SND_MPU401_UART=m CONFIG_SND_OPL3_LIB=m CONFIG_SND_OPL4_LIB=m CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m CONFIG_SND_DUMMY=m CONFIG_SND_VIRMIDI=m CONFIG_SND_MTPAV=m @@ -1815,87 +2517,102 @@ CONFIG_SND_MPU401=m # # ISA devices # -CONFIG_SND_AD1816A=m -CONFIG_SND_AD1848=m -CONFIG_SND_CS4231=m -CONFIG_SND_CS4232=m +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set CONFIG_SND_CS4236=m -CONFIG_SND_ES968=m -CONFIG_SND_ES1688=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set CONFIG_SND_ES18XX=m -CONFIG_SND_GUSCLASSIC=m -CONFIG_SND_GUSEXTREME=m -CONFIG_SND_GUSMAX=m -CONFIG_SND_INTERWAVE=m -CONFIG_SND_INTERWAVE_STB=m -CONFIG_SND_OPTI92X_AD1848=m -CONFIG_SND_OPTI92X_CS4231=m -CONFIG_SND_OPTI93X=m -CONFIG_SND_SB8=m +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set CONFIG_SND_SB16=m CONFIG_SND_SBAWE=m -CONFIG_SND_SB16_CSP=y +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set # CONFIG_SND_WAVEFRONT is not set -CONFIG_SND_ALS100=m -CONFIG_SND_AZT2320=m -CONFIG_SND_CMI8330=m -CONFIG_SND_DT019X=m -CONFIG_SND_OPL3SA2=m -CONFIG_SND_SGALAXY=m -CONFIG_SND_SSCAPE=m # # PCI devices # -CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m CONFIG_SND_ALI5451=m CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m CONFIG_SND_AU8810=m CONFIG_SND_AU8820=m CONFIG_SND_AU8830=m CONFIG_SND_AZT3328=m CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m CONFIG_SND_CS46XX=m CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CS4281=m +CONFIG_SND_CS5535AUDIO=m CONFIG_SND_EMU10K1=m -CONFIG_SND_KORG1212=m -CONFIG_SND_MIXART=m -CONFIG_SND_NM256=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_HDSP=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_YMFPCI=m -CONFIG_SND_ALS4000=m -CONFIG_SND_CMIPCI=m +CONFIG_SND_EMU10K1X=m CONFIG_SND_ENS1370=m CONFIG_SND_ENS1371=m CONFIG_SND_ES1938=m CONFIG_SND_ES1968=m -CONFIG_SND_MAESTRO3=m CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m CONFIG_SND_ICE1712=m CONFIG_SND_ICE1724=m CONFIG_SND_INTEL8X0=m CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m # -# ALSA USB devices +# USB devices # CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m # # PCMCIA devices # # CONFIG_SND_VXPOCKET is not set -# CONFIG_SND_VXP440 is not set -CONFIG_SND_PDAUDIOCF=m +# CONFIG_SND_PDAUDIOCF is not set # # Open Sound System @@ -1905,6 +2622,9 @@ CONFIG_SND_PDAUDIOCF=m # # USB support # +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1914,6 +2634,8 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set # # USB Host Controller Drivers @@ -1921,36 +2643,46 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_SPLIT_ISO=y CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_ISP116X_HCD=m CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m # # USB Device Class drivers # -CONFIG_USB_AUDIO=m +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m # -# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information # -CONFIG_USB_MIDI=m -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set CONFIG_USB_STORAGE_DATAFAB=y CONFIG_USB_STORAGE_FREECOM=y CONFIG_USB_STORAGE_ISD200=y CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_USBAT=y CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set CONFIG_HID_FF=y CONFIG_HID_PID=y CONFIG_LOGITECH_FF=y @@ -1958,64 +2690,50 @@ CONFIG_THRUSTMASTER_FF=y CONFIG_USB_HIDDEV=y CONFIG_USB_AIPTEK=m CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m CONFIG_USB_KBTAB=m CONFIG_USB_POWERMATE=m -CONFIG_USB_MTOUCH=m -CONFIG_USB_EGALAX=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set CONFIG_USB_XPAD=m CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m # # USB Imaging devices # CONFIG_USB_MDC800=m CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# -CONFIG_USB_DABUSB=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_W9968CF=m # -# USB Network adaptors +# USB Network Adapters # CONFIG_USB_CATC=m CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_USBNET=m - -# -# USB Host-to-Host Cables -# +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m CONFIG_USB_ALI_M5632=y CONFIG_USB_AN2720=y CONFIG_USB_BELKIN=y -CONFIG_USB_GENESYS=y -CONFIG_USB_NET1080=y -CONFIG_USB_PL2301=y - -# -# Intelligent USB Devices/Gadgets -# CONFIG_USB_ARMLINUX=y CONFIG_USB_EPSON2888=y -CONFIG_USB_ZAURUS=y -CONFIG_USB_CDCETHER=y - -# -# USB Network Adapters -# -CONFIG_USB_AX8817X=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_ZD1201=m +CONFIG_USB_MON=y # # USB port drivers @@ -2027,15 +2745,24 @@ CONFIG_USB_USS720=m # CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ANYDATA=m +CONFIG_USB_SERIAL_ARK3116=m CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m CONFIG_USB_SERIAL_VISOR=m CONFIG_USB_SERIAL_IPAQ=m CONFIG_USB_SERIAL_IR=m CONFIG_USB_SERIAL_EDGEPORT=m CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m CONFIG_USB_SERIAL_KEYSPAN_PDA=m CONFIG_USB_SERIAL_KEYSPAN=m CONFIG_USB_SERIAL_KEYSPAN_MPR=y @@ -2053,11 +2780,15 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y CONFIG_USB_SERIAL_KLSI=m CONFIG_USB_SERIAL_KOBIL_SCT=m CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m CONFIG_USB_SERIAL_SAFE=m CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_TI=m CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_EZUSB=y @@ -2065,22 +2796,111 @@ CONFIG_USB_EZUSB=y # USB Miscellaneous drivers # CONFIG_USB_EMI62=m -# CONFIG_USB_EMI26 is not set -CONFIG_USB_TIGL=m +CONFIG_USB_EMI26=m CONFIG_USB_AUERSWALD=m CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_LED=m # CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m CONFIG_USB_TEST=m +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + # # USB Gadget Support # # CONFIG_USB_GADGET is not set +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set + # # File systems # @@ -2088,6 +2908,8 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y CONFIG_EXT3_FS=m CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y @@ -2103,22 +2925,28 @@ CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m -# CONFIG_XFS_RT is not set +CONFIG_XFS_EXPORT=y CONFIG_XFS_QUOTA=y CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m CONFIG_MINIX_FS=m CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set CONFIG_QFMT_V2=y CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m # # CD-ROM/DVD Filesystems @@ -2128,6 +2956,7 @@ CONFIG_JOLIET=y CONFIG_ZISOFS=y CONFIG_ZISOFS_FS=y CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2135,6 +2964,8 @@ CONFIG_UDF_FS=m CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" # CONFIG_NTFS_FS is not set # @@ -2143,13 +2974,11 @@ CONFIG_VFAT_FS=m CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -2165,37 +2994,52 @@ CONFIG_EFS_FS=m # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=m CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_NAND=y +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set CONFIG_VXFS_FS=m # CONFIG_HPFS_FS is not set CONFIG_QNX4FS_FS=m -# CONFIG_QNX4FS_RW is not set CONFIG_SYSV_FS=m CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # CONFIG_NFS_FS=m CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_DIRECTIO=y CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=m CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_EXPERIMENTAL is not set CONFIG_NCP_FS=m CONFIG_NCPFS_PACKET_SIGNING=y CONFIG_NCPFS_IOCTL_LOCKING=y @@ -2205,8 +3049,10 @@ CONFIG_NCPFS_OS2_NS=y CONFIG_NCPFS_SMALLDOS=y CONFIG_NCPFS_NLS=y CONFIG_NCPFS_EXTRAS=y -# CONFIG_CODA_FS is not set +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set +CONFIG_9P_FS=m # # Partition Types @@ -2214,7 +3060,7 @@ CONFIG_NCPFS_EXTRAS=y CONFIG_PARTITION_ADVANCED=y # CONFIG_ACORN_PARTITION is not set CONFIG_OSF_PARTITION=y -# CONFIG_AMIGA_PARTITION is not set +CONFIG_AMIGA_PARTITION=y # CONFIG_ATARI_PARTITION is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y @@ -2223,10 +3069,10 @@ CONFIG_MINIX_SUBPARTITION=y CONFIG_SOLARIS_X86_PARTITION=y CONFIG_UNIXWARE_DISKLABEL=y # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y CONFIG_EFI_PARTITION=y # @@ -2234,7 +3080,7 @@ CONFIG_EFI_PARTITION=y # CONFIG_NLS=y CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m CONFIG_NLS_CODEPAGE_850=m @@ -2257,6 +3103,7 @@ CONFIG_NLS_CODEPAGE_874=m CONFIG_NLS_ISO8859_8=m CONFIG_NLS_CODEPAGE_1250=m CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m @@ -2273,41 +3120,68 @@ CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m # -# Profiling support +# Instrumentation Support # CONFIG_PROFILING=y CONFIG_OPROFILE=m +CONFIG_KPROBES=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y -CONFIG_EARLY_PRINTK=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_HIGHMEM is not set -CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_VM=y # CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_STACK_BACKTRACE_COLS=2 + +# +# Page alloc debug is incompatible with Software Suspend on i386 +# +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y CONFIG_X86_FIND_SMP_CONFIG=y CONFIG_X86_MPPARSE=y +CONFIG_DOUBLEFAULT=y # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y CONFIG_SECURITY_CAPABILITIES=y # CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_SECURITY_SELINUX_DEVELOP=y -# CONFIG_SECURITY_SELINUX_MLS is not set +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 # # Cryptographic options @@ -2317,32 +3191,51 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_DES=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y # # Library routines # +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m -CONFIG_X86_SMP=y -CONFIG_X86_HT=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_X86_BIOS_REBOOT=y -CONFIG_X86_TRAMPOLINE=y -CONFIG_X86_STD_RESOURCES=y -CONFIG_PC=y +CONFIG_KTIME_SCALAR=y diff --git a/.config.old b/.config.old index a1d48d7b8..8a7fee71e 100644 --- a/.config.old +++ b/.config.old @@ -1,44 +1,45 @@ +# i386 # # Automatically generated make config: don't edit # CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_SMP=y -# CONFIG_HOTPLUG_CPU is not set -CONFIG_SCHED_SMT=y - +# CONFIG_SMP is not set +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCALVERSION="" +# CONFIG_CRASH_DUMP is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_STANDALONE=y - +CONFIG_PREVENT_FIRMWARE_BUILD=y # # General setup # +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y -# CONFIG_NUMA is not set -# CONFIG_PREEMPT is not set -# CONFIG_IRQBALANCE is not set +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_CFQ=y CONFIG_POSIX_MQUEUE=y -CONFIG_EDD=m -# CONFIG_SMBIOS is not set -CONFIG_IRQSTACKS=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y # # Loadable module support @@ -47,107 +48,67 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y - -# -# Power management options (ACPI, APM) -# -CONFIG_PM=y -# CONFIG_SOFTWARE_SUSPEND is not set -# CONFIG_PM_DISK is not set - -# -# ACPI (Advanced Configuration and Power Interface) Support -# -CONFIG_ACPI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_THERMAL=y -CONFIG_ACPI_ASUS=m -CONFIG_ACPI_TOSHIBA=m -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_BUS=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_NUMA=y - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_PROC_INTF is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -# CONFIG_CPU_FREQ_24_API is not set -CONFIG_CPU_FREQ_TABLE=y - +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GOMMCONFIG is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_MMCONFIG=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_MSI=y CONFIG_PCI_LEGACY_PROC=y -# CONFIG_PCI_NAMES is not set -CONFIG_PCI_USE_VECTOR=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +CONFIG_HOTPLUG_PCI_FAKE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set CONFIG_ISA=y # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SCx200 is not set CONFIG_HOTPLUG=y +# CONFIG_DEBUG_KOBJECT is not set # # PCMCIA/CardBus support # -CONFIG_PCMCIA=m +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y # CONFIG_PCMCIA_DEBUG is not set CONFIG_YENTA=y CONFIG_CARDBUS=y CONFIG_I82092=m -CONFIG_I82365=m -CONFIG_TCIC=m -CONFIG_PCMCIA_PROBE=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=y -# CONFIG_HOTPLUG_PCI_FAKE is not set -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_ACPI is not set -# CONFIG_HOTPLUG_PCI_CPCI is not set -CONFIG_HOTPLUG_PCI_PCIE=m -CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE=y -CONFIG_HOTPLUG_PCI_SHPC=m -CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y -# CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY is not set +CONFIG_PD6729=m +CONFIG_PCMCIA_IOCTL=y + +CONFIG_PCCARD=y +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_WBSD=y +CONFIG_MMC_SDHCI=m + +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_MTHCA=m +# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_IPATH_CORE=m +CONFIG_INFINIBAND_IPATH=m # # Executable file formats # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_MISC=y # # Device Drivers @@ -158,26 +119,28 @@ CONFIG_BINFMT_MISC=m # CONFIG_FW_LOADER=y +# CONFIG_SPI is not set + # # Memory Technology Devices (MTD) # CONFIG_MTD=m # CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=m +CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CONCAT=m -CONFIG_MTD_REDBOOT_PARTS=m -CONFIG_MTD_CMDLINE_PARTS=m - +CONFIG_MTD_CMDLINE_PARTS=y # # User Modules And Translation Layers # CONFIG_MTD_CHAR=m CONFIG_MTD_BLOCK=m CONFIG_MTD_BLOCK_RO=m +CONFIG_MTD_BLOCK2MTD=m CONFIG_FTL=m CONFIG_NFTL=m CONFIG_NFTL_RW=y CONFIG_INFTL=m +CONFIG_RFD_FTL=m # # RAM/ROM/Flash chip drivers @@ -202,16 +165,15 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_PNC2000 is not set CONFIG_MTD_SC520CDP=m CONFIG_MTD_NETSC520=m -CONFIG_MTD_SBC_GXX=m -CONFIG_MTD_ELAN_104NC=m +# CONFIG_MTD_SBC_GXX is not set CONFIG_MTD_SCx200_DOCFLASH=m -CONFIG_MTD_AMD76XROM=m -CONFIG_MTD_ICH2ROM=m +# CONFIG_MTD_AMD76XROM is not set CONFIG_MTD_SCB2_FLASH=m # CONFIG_MTD_NETtel is not set # CONFIG_MTD_DILNETPC is not set -CONFIG_MTD_L440GX=m +# CONFIG_MTD_L440GX is not set CONFIG_MTD_PCI=m +CONFIG_MTD_TS5500=m # # Self-contained MTD device drivers @@ -241,18 +203,32 @@ CONFIG_MTD_DOCPROBE_ADDRESS=0 CONFIG_MTD_NAND=m # CONFIG_MTD_NAND_VERIFY_WRITE is not set CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_NANDSIM=m +# CONFIG_MTD_ONENAND is not set + +CONFIG_MTD_REDBOOT_PARTS=m +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_CFI_AMDSTD_RETRY=3 +# CONFIG_MTD_XIP is not set +# CONFIG_MTD_ICHXROM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y # # Parallel port support # CONFIG_PARPORT=m CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m CONFIG_PARPORT_SERIAL=m # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_OTHER is not set CONFIG_PARPORT_1284=y # @@ -266,13 +242,37 @@ CONFIG_PNP=y # CONFIG_ISAPNP=y # CONFIG_PNPBIOS is not set +# CONFIG_ACPI_CONTAINER is not set +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +# CONFIG_ACPI_HOTKEY is not set # # Block devices # CONFIG_BLK_DEV_FD=m # CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m CONFIG_BLK_CPQ_DA=m CONFIG_BLK_CPQ_CISS_DA=m CONFIG_CISS_SCSI_TAPE=y @@ -282,12 +282,13 @@ CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_ATIIXP=y CONFIG_LBD=y -# CONFIG_DCSSBLK is not set - +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y # # ATA/ATAPI/MFM/RLL support @@ -304,20 +305,19 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECS=m CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=m +# CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y +# CONFIG_BLK_DEV_IDE_SATA 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_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y CONFIG_BLK_DEV_IDEPNP=y CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y @@ -326,11 +326,9 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_RZ1000=y CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDE_TCQ is not set # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y CONFIG_BLK_DEV_AEC62XX=y CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set @@ -340,15 +338,16 @@ CONFIG_BLK_DEV_TRIFLEX=y CONFIG_BLK_DEV_CY82C693=y CONFIG_BLK_DEV_CS5520=y CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y CONFIG_BLK_DEV_HPT34X=y CONFIG_BLK_DEV_HPT366=y +CONFIG_BLK_DEV_IT821X=y # CONFIG_BLK_DEV_SC1200 is not set CONFIG_BLK_DEV_PIIX=y # CONFIG_BLK_DEV_NS87415 is not set CONFIG_BLK_DEV_PDC202XX_OLD=y # CONFIG_PDC202XX_BURST is not set CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y CONFIG_BLK_DEV_SVWKS=y CONFIG_BLK_DEV_SIIMAGE=y CONFIG_BLK_DEV_SIS5513=y @@ -359,7 +358,6 @@ CONFIG_BLK_DEV_VIA82CXXX=y CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y -# CONFIG_DMA_NONPCI is not set # CONFIG_BLK_DEV_HD is not set # @@ -377,25 +375,29 @@ CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=m CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SPI_ATTRS=y -CONFIG_SCSI_FC_ATTRS=y +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_RAID_ATTRS=m + +CONFIG_ISCSI_TCP=m # # SCSI low-level drivers # CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m # CONFIG_SCSI_7000FASST is not set CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 @@ -415,66 +417,68 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000 CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_MEGARAID=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m CONFIG_SCSI_SATA=y CONFIG_SCSI_SATA_SVW=m CONFIG_SCSI_ATA_PIIX=m CONFIG_SCSI_SATA_PROMISE=m CONFIG_SCSI_SATA_VIA=m -CONFIG_BLK_DEV_CARMEL=m +CONFIG_BLK_DEV_SX8=m CONFIG_SCSI_SATA_VITESSE=m CONFIG_SCSI_SATA_SIL=m CONFIG_SCSI_SATA_SIS=m CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_PDC_ADMA=m CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_INITIO=m # CONFIG_SCSI_OMIT_FLASHPOINT is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_PIO is not set CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_SCSI_GDTH=m -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set CONFIG_SCSI_IPS=m CONFIG_SCSI_INIA100=m CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m # CONFIG_SCSI_IZIP_EPP16 is not set # CONFIG_SCSI_IZIP_SLOW_CTR is not set -# CONFIG_SCSI_NCR53C406A is not set CONFIG_SCSI_SYM53C8XX_2=m CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PSI240I is not set -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=m -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set +CONFIG_SCSI_DC395x=m # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_DC390T=m -CONFIG_SCSI_QLA2XXX=m +CONFIG_SCSI_QLA_FC=m +# FIXME: Turn off for FC6 - Move to external firmware loader. +CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y CONFIG_SCSI_QLA21XX=m CONFIG_SCSI_QLA22XX=m CONFIG_SCSI_QLA2300=m CONFIG_SCSI_QLA2322=m +CONFIG_SCSI_QLA24XX=m CONFIG_SCSI_QLA6312=m -CONFIG_SCSI_QLA6322=m # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_LPFC=m # # PCMCIA SCSI adapter support @@ -486,11 +490,6 @@ CONFIG_PCMCIA_QLOGIC=m CONFIG_PCMCIA_SYM53C500=m -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - # # Multi-device support (RAID and LVM) # @@ -500,19 +499,28 @@ CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID5=m +CONFIG_MD_RAID5_RESHAPE=y CONFIG_MD_RAID6=m +CONFIG_MD_RAID10=m CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m CONFIG_BLK_DEV_DM=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m CONFIG_DM_CRYPT=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m # # Fusion MPT device support # -CONFIG_FUSION=m +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set CONFIG_FUSION_CTL=m CONFIG_FUSION_LAN=m +CONFIG_FUSION_SAS=m # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -528,7 +536,7 @@ CONFIG_IEEE1394_OUI_DB=y # # Device Drivers # -# CONFIG_IEEE1394_PCILYNX is not set +CONFIG_IEEE1394_PCILYNX=m CONFIG_IEEE1394_OHCI1394=m # @@ -537,45 +545,48 @@ CONFIG_IEEE1394_OHCI1394=m CONFIG_IEEE1394_VIDEO1394=m CONFIG_IEEE1394_SBP2=m # CONFIG_IEEE1394_SBP2_PHYS_DMA is not set -# CONFIG_IEEE1394_ETH1394 is not set +CONFIG_IEEE1394_ETH1394=m CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set # # I2O device support # CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m -CONFIG_I2O_CONFIG=y +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set # # Networking support # CONFIG_NET=y +# CONFIG_NETDEBUG is not set + +# CONFIG_TCP_CONG_ADVANCED is not set # # Networking options # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y CONFIG_UNIX=y CONFIG_NET_KEY=m CONFIG_INET=y +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=m CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_MULTIPATH_RR=m +CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m +CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m +CONFIG_IP_ROUTE_MULTIPATH_DRR=m # CONFIG_IP_PNP is not set CONFIG_NET_IPIP=m CONFIG_NET_IPGRE=m @@ -590,7 +601,8 @@ CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m CONFIG_NETCONSOLE=m # CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y # # IP: Virtual Server Configuration @@ -614,16 +626,50 @@ CONFIG_IP_VS_SED=m CONFIG_IP_VS_NQ=m CONFIG_IP_VS_FTP=m - CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_TUNNEL=m -# CONFIG_DECNET is not set +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +# CONFIG_DECNET_NF_GRABULATOR is not set CONFIG_BRIDGE=m CONFIG_NETFILTER=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -631,85 +677,82 @@ CONFIG_BRIDGE_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_POLICY=m CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_MATCH_PHYSDEV=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m # # IPv6: Netfilter Configuration # -# CONFIG_IP6_NF_QUEUE is not set +CONFIG_IP6_NF_QUEUE=m CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_EUI64=m CONFIG_IP6_NF_MATCH_FRAG=m CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OPTS=m CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_POLICY=m CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_HL=m # # Bridge: Netfilter Configuration @@ -733,6 +776,7 @@ CONFIG_BRIDGE_EBT_MARK_T=m CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m CONFIG_XFRM=y CONFIG_XFRM_USER=y @@ -745,7 +789,7 @@ CONFIG_IP_SCTP=m # CONFIG_SCTP_HMAC_NONE is not set # CONFIG_SCTP_HMAC_SHA1 is not set CONFIG_SCTP_HMAC_MD5=y -# CONFIG_ATM is not set +CONFIG_ATM=m CONFIG_VLAN_8021Q=m CONFIG_LLC=m # CONFIG_LLC2 is not set @@ -753,10 +797,6 @@ CONFIG_IPX=m # CONFIG_IPX_INTERN is not set CONFIG_ATALK=m CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y CONFIG_IPDDP_DECAP=y @@ -765,8 +805,18 @@ CONFIG_IPDDP_DECAP=y CONFIG_NET_DIVERT=y # CONFIG_ECONET is not set CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set +CONFIG_IP_DCCP=m +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +# CONFIG_IP_DCCP_DEBUG is not set +CONFIG_IP_DCCP_UNLOAD_HACK=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set # # QoS and/or fair queueing @@ -774,7 +824,6 @@ CONFIG_WAN_ROUTER=m CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m @@ -784,9 +833,7 @@ CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_DELAY=m - -CONFIG_NET_QOS=y +CONFIG_NET_SCH_NETEM=m CONFIG_NET_ESTIMATOR=y CONFIG_NET_CLS=y CONFIG_NET_CLS_TCINDEX=m @@ -794,14 +841,27 @@ CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_POLICE=y +# CONFIG_NET_ACT_POLICE is not set +CONFIG_CLS_U32_PERF=y +CONFIG_NET_CLS_IND=y +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m # # Network testing # -# CONFIG_NET_PKTGEN is not set +CONFIG_NET_PKTGEN=m CONFIG_NETDEVICES=y # @@ -812,33 +872,64 @@ CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_EQUALIZER=m CONFIG_TUN=m -CONFIG_ETHERTAP=m CONFIG_NET_SB1000=m +# +# ATM +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_CLIP=m +CONFIG_ATM_LANE=m +CONFIG_ATM_BR2684=m +CONFIG_NET_SCH_ATM=m +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +CONFIG_ATM_AMBASSADOR=m +CONFIG_ATM_HORIZON=m +CONFIG_ATM_FORE200E_MAYBE=m +CONFIG_ATM_HE=m +CONFIG_PPPOATM=m +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_IA is not set + + +# CONFIG_ATM_CLIP_NO_ICMP is not set +# CONFIG_ATM_MPOA is not set +# CONFIG_ATM_BR2684_IPFILTER is not set +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +# CONFIG_ATM_ZATM_DEBUG is not set +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_FORE200E_PCA is not set +# CONFIG_ATM_HE_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +# CONFIG_ATM_IA_DEBUG is not set + + # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_PHYLIB=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m CONFIG_MII=m CONFIG_HAPPYMEAL=m CONFIG_SUNGEM=m CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m CONFIG_VORTEX=m CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -CONFIG_ULTRA=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI52=m -CONFIG_NI65=m # # Tulip family network device support @@ -847,7 +938,6 @@ CONFIG_NET_TULIP=y CONFIG_DE2104X=m CONFIG_TULIP=m # CONFIG_TULIP_NAPI is not set - # CONFIG_TULIP_MWI is not set CONFIG_TULIP_MMIO=y # CONFIG_NI5010 is not set @@ -856,21 +946,8 @@ CONFIG_DE4X5=m CONFIG_WINBOND_840=m CONFIG_DM9102=m CONFIG_PCMCIA_XIRCOM=m -# CONFIG_AT1700 is not set -CONFIG_DEPCA=m +CONFIG_ULI526X=m CONFIG_HP100=m -# CONFIG_NET_ISA is not set -# CONFIG_EWRK3 is not set -CONFIG_E2100=m -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_ZNET=m -CONFIG_SEEQ8005=m CONFIG_LNE390=m CONFIG_NE3210=m CONFIG_ES3210=m @@ -880,53 +957,56 @@ CONFIG_AMD8111_ETH=m CONFIG_AMD8111E_NAPI=y CONFIG_ADAPTEC_STARFIRE=m CONFIG_ADAPTEC_STARFIRE_NAPI=y -CONFIG_AC3200=m -CONFIG_APRICOT=m CONFIG_B44=m -CONFIG_CS89x0=m +CONFIG_BNX2=m CONFIG_DGRS=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set +# CONFIG_EEPRO100 is not set CONFIG_E100=m -CONFIG_E100_NAPI=y CONFIG_FEALNX=m CONFIG_FORCEDETH=m CONFIG_NATSEMI=m CONFIG_NE2K_PCI=m CONFIG_8139CP=m CONFIG_8139TOO=m -CONFIG_8139TOO_PIO=y +# CONFIG_8139TOO_PIO is not set # CONFIG_8139TOO_TUNE_TWISTER is not set CONFIG_8139TOO_8129=y # CONFIG_8139_OLD_RX_RESET is not set -CONFIG_8139_RXBUF_IDX=2 CONFIG_SIS900=m +CONFIG_SIS190=m CONFIG_EPIC100=m CONFIG_SUNDANCE=m # CONFIG_SUNDANCE_MMIO is not set CONFIG_TLAN=m CONFIG_VIA_RHINE=m CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m CONFIG_NET_POCKET=y CONFIG_ATP=m CONFIG_DE600=m CONFIG_DE620=m +CONFIG_CASSINI=m +# CONFIG_FEC_8XX is not set # # Ethernet (1000 Mbit) # -CONFIG_NET_GIGE=y CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set CONFIG_DL2K=m CONFIG_E1000=m CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m -CONFIG_SK98LIN=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +# CONFIG_SK98LIN is not set +CONFIG_SKGE=m CONFIG_TIGON3=m +CONFIG_SKY2=m # # Ethernet (10000 Mbit) @@ -935,6 +1015,8 @@ CONFIG_IXGB=m CONFIG_IXGB_NAPI=y CONFIG_S2IO=m CONFIG_S2IO_NAPI=y +CONFIG_CHELSIO_T1=m + CONFIG_FDDI=y # CONFIG_DEFXX is not set CONFIG_SKFP=m @@ -949,7 +1031,11 @@ CONFIG_PPP_DEFLATE=m CONFIG_IPPP_FILTER=y # CONFIG_PPP_BSDCOMP is not set CONFIG_PPPOE=m -# CONFIG_SLIP is not set +CONFIG_PPP_MPPE=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set # # Wireless LAN (non-hamradio) @@ -961,7 +1047,6 @@ CONFIG_NET_RADIO=y # # CONFIG_STRIP is not set # CONFIG_ARLAN is not set -CONFIG_WAVELAN=m CONFIG_PCMCIA_WAVELAN=m CONFIG_PCMCIA_NETWAVE=m @@ -973,31 +1058,62 @@ CONFIG_PCMCIA_NETWAVE=m # # Wireless 802.11b ISA/PCI cards support # +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_IPW2100=m +CONFIG_IPW2200=m +# CONFIG_IPW2100_DEBUG is not set +# CONFIG_IPW2200_DEBUG is not set CONFIG_AIRO=m CONFIG_HERMES=m CONFIG_PLX_HERMES=m CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m CONFIG_PCI_HERMES=m CONFIG_ATMEL=m CONFIG_PCI_ATMEL=m CONFIG_PRISM54=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y # # Wireless 802.11b Pcmcia/Cardbus cards support # CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m CONFIG_AIRO_CS=m CONFIG_PCMCIA_ATMEL=m CONFIG_PCMCIA_WL3501=m CONFIG_NET_WIRELESS=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +CONFIG_HOSTAP=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_CS=m # # Token Ring devices # -# CONFIG_TR is not set +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# Broken with gcc4.1 +# CONFIG_TMS380TR is not set +CONFIG_TMSPCI=m +CONFIG_ABYSS=m +CONFIG_IBMLS=m +CONFIG_PCMCIA_IBMTR=m + CONFIG_NET_FC=y -CONFIG_RCPCI=m # CONFIG_SHAPER is not set # @@ -1039,6 +1155,7 @@ CONFIG_DONGLE=y CONFIG_ESI_DONGLE=m CONFIG_ACTISYS_DONGLE=m CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m CONFIG_IRPORT_SIR=m # CONFIG_DONGLE_OLD is not set CONFIG_LITELINK_DONGLE=m @@ -1051,14 +1168,12 @@ CONFIG_ACT200L_DONGLE=m CONFIG_USB_IRDA=m CONFIG_NSC_FIR=m CONFIG_SIGMATEL_FIR=m -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -# CONFIG_VIA_FIR is not set - - +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m # # Bluetooth support @@ -1072,6 +1187,7 @@ CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_BNEP=m CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m # # Bluetooth device drivers @@ -1080,7 +1196,6 @@ CONFIG_BT_HCIUSB=m CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_BCSP_TXCRC=y CONFIG_BT_HCIDTL1=m CONFIG_BT_HCIBT3C=m CONFIG_BT_HCIBLUECARD=m @@ -1089,11 +1204,7 @@ CONFIG_BT_HCIVHCI=m CONFIG_BT_HCIUSB_SCO=y CONFIG_BT_HCIBCM203X=m CONFIG_BT_HCIBFUSB=m -CONFIG_BT_CMTP=m -CONFIG_BT_HCIUSB_SCO=m -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_USB_BLUETOOTH_TTY=m +CONFIG_BT_HCIBPA10X=m # # ISDN subsystem @@ -1101,9 +1212,7 @@ CONFIG_USB_BLUETOOTH_TTY=m CONFIG_ISDN=m CONFIG_ISDN_I4L=m -CONFIG_ISDN_DRV_AVMB1_B1ISA=m CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_T1ISA=m CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m CONFIG_ISDN_DRV_AVMB1_T1PCI=m CONFIG_ISDN_DRV_AVMB1_C4=m @@ -1118,41 +1227,27 @@ CONFIG_DE_AOC=y CONFIG_ISDN_AUDIO=y CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -CONFIG_ISDN_DRV_SC=m -CONFIG_ISDN_DRV_ACT2000=m -CONFIG_ISDN_DRV_TPAM=m CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y CONFIG_ISDN_DRV_AVMB1_AVM_CS=m CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_DIVERSION=m CONFIG_HISAX_EURO=y CONFIG_HISAX_1TR6=y CONFIG_HISAX_NI1=y CONFIG_HISAX_MAX_CARDS=8 -CONFIG_HISAX_16_0=y CONFIG_HISAX_16_3=y CONFIG_HISAX_TELESPCI=y CONFIG_HISAX_S0BOX=y -CONFIG_HISAX_AVM_A1=y CONFIG_HISAX_FRITZPCI=y CONFIG_HISAX_AVM_A1_PCMCIA=y CONFIG_HISAX_ELSA=y -CONFIG_HISAX_IX1MICROR2=y CONFIG_HISAX_DIEHLDIVA=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y CONFIG_HISAX_SEDLBAUER=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y CONFIG_HISAX_NETJET=y CONFIG_HISAX_NETJET_U=y CONFIG_HISAX_NICCY=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=y CONFIG_HISAX_BKM_A4T=y CONFIG_HISAX_SCT_QUADRO=y CONFIG_HISAX_GAZEL=y @@ -1163,7 +1258,7 @@ CONFIG_HISAX_ENTERNOW_PCI=y # CONFIG_HISAX_DEBUG is not set CONFIG_HISAX_AVM_A1_CS=m CONFIG_HISAX_ST5481=m -CONFIG_HISAX_HFCUSB=m +# CONFIG_HISAX_HFCUSB is not set CONFIG_HISAX_FRITZ_PCIPNP=m CONFIG_HISAX_NO_SENDCOMPLETE=y CONFIG_HISAX_NO_LLC=y @@ -1171,6 +1266,7 @@ CONFIG_HISAX_NO_KEYPAD=y CONFIG_HISAX_SEDLBAUER_CS=m CONFIG_HISAX_ELSA_CS=m CONFIG_HISAX_TELES_CS=m +CONFIG_HISAX_HFC4S8S=m CONFIG_ISDN_DRV_LOOP=m CONFIG_HYSDN=m @@ -1207,6 +1303,12 @@ CONFIG_ISDN_DIVAS_DIVACAPI=m CONFIG_ISDN_DIVAS_USERIDI=m CONFIG_ISDN_DIVAS_MAINT=m +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + # # Telephony Support # @@ -1233,16 +1335,15 @@ CONFIG_INPUT_EVDEV=y # Input I/O drivers # CONFIG_GAMEPORT=m -CONFIG_SOUND_GAMEPORT=m CONFIG_GAMEPORT_NS558=m CONFIG_GAMEPORT_L4=m CONFIG_GAMEPORT_EMU10K1=m -CONFIG_GAMEPORT_VORTEX=m CONFIG_GAMEPORT_FM801=m -CONFIG_GAMEPORT_CS461x=m CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_RAW=m + # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PCIPS2 is not set @@ -1259,10 +1360,6 @@ CONFIG_KEYBOARD_ATKBD=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y CONFIG_MOUSE_SERIAL=m -CONFIG_MOUSE_INPORT=m -CONFIG_MOUSE_ATIXL=y -CONFIG_MOUSE_LOGIBM=m -CONFIG_MOUSE_PC110PAD=m CONFIG_MOUSE_VSXXXAA=m CONFIG_INPUT_JOYSTICK=y CONFIG_JOYSTICK_ANALOG=m @@ -1284,16 +1381,20 @@ CONFIG_JOYSTICK_MAGELLAN=m CONFIG_JOYSTICK_SPACEORB=m CONFIG_JOYSTICK_SPACEBALL=m CONFIG_JOYSTICK_STINGER=m -CONFIG_JOYSTICK_TWIDDLER=m CONFIG_JOYSTICK_DB9=m CONFIG_JOYSTICK_GAMECON=m CONFIG_JOYSTICK_TURBOGRAFX=m -# CONFIG_INPUT_JOYDUMP is not set +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_TWIDJOY=m CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m CONFIG_INPUT_MISC=y CONFIG_INPUT_PCSPKR=m -# CONFIG_INPUT_UINPUT is not set +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_WISTRON_BTNS=m # # Character devices @@ -1305,10 +1406,16 @@ CONFIG_SERIAL_NONSTANDARD=y CONFIG_ROCKETPORT=m CONFIG_SYNCLINK=m CONFIG_SYNCLINKMP=m +# CONFIG_SYNCLINK_GT is not set CONFIG_N_HDLC=m -CONFIG_STALDRV=y +# CONFIG_STALDRV is not set # CONFIG_FTAPE is not set CONFIG_IBM_ASM=m +# CONFIG_TCG_TPM is not set +# CONFIG_TCG_NSC is not set +# CONFIG_TCG_ATMEL is not set +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set # # Serial drivers @@ -1317,17 +1424,16 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CS=m # CONFIG_SERIAL_8250_ACPI is not set -CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y -# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_DETECT_IRQ=y -CONFIG_SERIAL_8250_MULTIPORT=y CONFIG_SERIAL_8250_RSA=y # CONFIG_COMPUTONE is not set # CONFIG_CYCLADES is not set # CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set # CONFIG_ESPSERIAL is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set @@ -1338,6 +1444,7 @@ CONFIG_SERIAL_8250_RSA=y # CONFIG_RIO is not set # CONFIG_STALLION is not set # CONFIG_ISTALLION is not set +# CONFIG_SERIAL_JSM is not set # # Non-8250 serial port support @@ -1345,7 +1452,6 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 # CONFIG_LEGACY_PTYS is not set CONFIG_PRINTER=m CONFIG_LP_CONSOLE=y @@ -1368,69 +1474,102 @@ CONFIG_I2C_ALGOPCF=m # # I2C Hardware Bus support # + +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +CONFIG_I2C_VOODOO3=m CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m CONFIG_I2C_ALI15X3=m CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m CONFIG_I2C_AMD8111=m CONFIG_I2C_I801=m CONFIG_I2C_I810=m -CONFIG_I2C_ISA=m -CONFIG_I2C_NFORCE2=m CONFIG_I2C_PIIX4=m -CONFIG_I2C_PROSAVAGE=m -CONFIG_I2C_SAVAGE4=m # CONFIG_SCx200_ACB is not set CONFIG_I2C_SIS5595=m CONFIG_I2C_SIS630=m CONFIG_I2C_SIS96X=m CONFIG_I2C_VIA=m CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m + # CONFIG_I2C_ELEKTOR is not set CONFIG_I2C_PARPORT=m CONFIG_I2C_PARPORT_LIGHT=m # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set -# CONFIG_I2C_PARPORT is not set -CONFIG_I2C_ALI1563=m -# CONFIG_I2C_PARPORT_LIGHT is not set - - +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_PCA_ISA=m +CONFIG_I2C_STUB=m # # I2C Hardware Sensors Chip support # -CONFIG_I2C_SENSOR=m CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_HDAPS=m CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m CONFIG_SENSORS_LM78=m CONFIG_SENSORS_LM80=m CONFIG_SENSORS_LM83=m CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_LM87=m CONFIG_SENSORS_LM90=m -CONFIG_SENSORS_W83L785TS=m -CONFIG_SENSORS_FSCHER=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX6875=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PCA9539=m CONFIG_SENSORS_PCF8574=m CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_RTC8564=m -CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_W83792D=m +CONFIG_RTC_X1205_I2C=m + +CONFIG_W1=m +CONFIG_W1_DS2433_CRC=y + +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS9490=m +CONFIG_W1_MASTER_DS9490_BRIDGE=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m # # Mice # -CONFIG_BUSMOUSE=m -# CONFIG_QIC02_TAPE is not set -CONFIG_CRASH=m # # IPMI @@ -1438,9 +1577,9 @@ CONFIG_CRASH=m CONFIG_IPMI_HANDLER=m # CONFIG_IPMI_PANIC_EVENT is not set CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m CONFIG_IPMI_WATCHDOG=m CONFIG_IPMI_SI=m +CONFIG_IPMI_POWEROFF=m # # Watchdog Cards @@ -1448,15 +1587,13 @@ CONFIG_IPMI_SI=m CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set CONFIG_SOFT_WATCHDOG=m -CONFIG_WDT=m # CONFIG_WDT_501 is not set CONFIG_WDTPCI=m CONFIG_WDT_501_PCI=y -CONFIG_PCWATCHDOG=m -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set CONFIG_I8XX_TCO=m # CONFIG_MIXCOMWD is not set # CONFIG_SCx200_WDT is not set @@ -1464,20 +1601,36 @@ CONFIG_I8XX_TCO=m CONFIG_W83877F_WDT=m CONFIG_W83627HF_WDT=m CONFIG_MACHZ_WDT=m -CONFIG_SC520_WDT=m -CONFIG_AMD7XX_TCO=m +# CONFIG_SC520_WDT is not set CONFIG_ALIM7101_WDT=m CONFIG_ALIM1535_WDT=m -CONFIG_SC1200_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_CPU5_WDT=m +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_I6300ESB_WDT=m +# CONFIG_SBC8360_WDT is not set +CONFIG_W83977F_WDT=m CONFIG_PCIPCWATCHDOG=m CONFIG_USBPCWATCHDOG=m - +# CONFIG_SBC_EPX_C3_WATCHDOG is not set CONFIG_HW_RANDOM=m -CONFIG_NVRAM=m +CONFIG_NVRAM=y CONFIG_RTC=y +CONFIG_RTC_CLASS=m +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_EP93XX is not set +# CONFIG_RTC_DRV_SA1100 is not set +# CONFIG_RTC_DRV_TEST is not set CONFIG_DTLK=m CONFIG_R3964=m # CONFIG_APPLICOM is not set @@ -1492,29 +1645,30 @@ CONFIG_AGP_ATI=y CONFIG_AGP_AMD=y CONFIG_AGP_AMD64=y CONFIG_AGP_INTEL=y -CONFIG_AGP_INTEL_MCH=y CONFIG_AGP_NVIDIA=y CONFIG_AGP_SIS=y CONFIG_AGP_SWORKS=y CONFIG_AGP_VIA=y CONFIG_AGP_EFFICEON=y -CONFIG_DRM=y +CONFIG_DRM=m CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m CONFIG_DRM_I810=m CONFIG_DRM_I830=m CONFIG_DRM_MGA=m CONFIG_DRM_SIS=m - +CONFIG_DRM_SAVAGE=m +CONFIG_DRM_I915=m +CONFIG_DRM_VIA=m # # PCMCIA character devices # CONFIG_SYNCLINK_CS=m - +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m CONFIG_MWAVE=m # CONFIG_RAW_DRIVER is not set @@ -1525,6 +1679,10 @@ CONFIG_HANGCHECK_TIMER=m # Multimedia devices # CONFIG_VIDEO_DEV=m +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +# CONFIG_VIDEO_VIVI is not set # # Video For Linux @@ -1533,59 +1691,65 @@ CONFIG_VIDEO_DEV=m # # Video Adapters # +CONFIG_VIDEO_AUDIO_DECODER=m CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_BT848_DVB=y CONFIG_VIDEO_BWQCAM=m -CONFIG_VIDEO_CQCAM=m -CONFIG_VIDEO_W9966=m CONFIG_VIDEO_CPIA=m CONFIG_VIDEO_CPIA_PP=m CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_DECODER=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_VIDEO_SAA5246A=m CONFIG_VIDEO_SAA5249=m -CONFIG_TUNER_3036=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m CONFIG_VIDEO_ZORAN=m CONFIG_VIDEO_ZORAN_BUZ=m CONFIG_VIDEO_ZORAN_DC10=m CONFIG_VIDEO_ZORAN_DC30=m CONFIG_VIDEO_ZORAN_LML33=m CONFIG_VIDEO_ZORAN_LML33R10=m -CONFIG_VIDEO_MEYE=m -CONFIG_VIDEO_SAA7134=m -CONFIG_VIDEO_MXB=m -CONFIG_VIDEO_DPC=m -CONFIG_VIDEO_HEXIUM_ORION=m -CONFIG_VIDEO_HEXIUM_GEMINI=m -CONFIG_VIDEO_CX88=m -CONFIG_VIDEO_SAA5246A=m +CONFIG_TUNER_3036=m # # Radio Adapters # -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m CONFIG_RADIO_GEMTEK_PCI=m CONFIG_RADIO_MAXIRADIO=m CONFIG_RADIO_MAESTRO=m CONFIG_RADIO_MIROPCM20=m CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m # # Digital Video Broadcasting Devices # -# CONFIG_DVB is not set +CONFIG_DVB=y CONFIG_DVB_CORE=m # @@ -1593,19 +1757,13 @@ CONFIG_DVB_CORE=m # CONFIG_DVB_STV0299=m # CONFIG_DVB_SP887X is not set -# CONFIG_DVB_ALPS_TDLB7 is not set -CONFIG_DVB_ALPS_TDMB7=m -CONFIG_DVB_ATMEL_AT76C651=m CONFIG_DVB_CX24110=m -CONFIG_DVB_GRUNDIG_29504_491=m -CONFIG_DVB_GRUNDIG_29504_401=m CONFIG_DVB_MT312=m CONFIG_DVB_VES1820=m CONFIG_DVB_VES1X93=m -CONFIG_DVB_TWINHAN_DST=m CONFIG_DVB_TTUSB_DEC=m CONFIG_DVB_BT8XX=m -# CONFIG_DVB_TDA1004X is not set +CONFIG_DVB_TDA1004X=m CONFIG_DVB_NXT6000=m # @@ -1627,7 +1785,43 @@ CONFIG_DVB_TTUSB_BUDGET=m # # Supported FlexCopII (B2C2) Adapters # -CONFIG_DVB_B2C2_SKYSTAR=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 +CONFIG_DVB_OR51132=m +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_LGDT330X=m + +CONFIG_DVB_S5H1420=m +CONFIG_DVB_SP8870=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA10021=m + CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m CONFIG_VIDEO_VIDEOBUF=m @@ -1644,15 +1838,17 @@ CONFIG_FB=y CONFIG_FB_VGA16=m CONFIG_FB_VESA=y CONFIG_VIDEO_SELECT=y -CONFIG_FB_HGA=m +# CONFIG_FB_HGA is not set CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_DEBUG is not set +# CONFIG_FB_RIVA_I2C is not set CONFIG_FB_I810=m CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y CONFIG_FB_MATROX=m CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_G=y CONFIG_FB_MATROX_I2C=m CONFIG_FB_MATROX_MAVEN=m CONFIG_FB_MATROX_MULTIHEAD=y @@ -1664,7 +1860,6 @@ CONFIG_FB_ATY128=m CONFIG_FB_ATY=m CONFIG_FB_ATY_CT=y CONFIG_FB_ATY_GX=y -# CONFIG_FB_ATY_XL_INIT is not set # CONFIG_FB_SIS is not set CONFIG_FB_SIS_300=y CONFIG_FB_SIS_315=y @@ -1677,17 +1872,35 @@ CONFIG_FB_KYRO=m # CONFIG_FB_PM2 is not set # CONFIG_FB_PM2_FIFO_DISCONNECT is not set # CONFIG_FB_ASILIANT is not set -CONFIG_FB_HGA_ACCEL=y CONFIG_FB_3DFX_ACCEL=y CONFIG_FB_TRIDENT_ACCEL=y +CONFIG_FB_CIRRUS=m +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_ARC is not set +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# 2.6.12-rc1-bk2 = Nvidia fb crashes. +# CONFIG_FB_NVIDIA is not set +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_CYBLA=m +# CONFIG_FB_FIRMWARE_EDID is not set # # Console display driver support # CONFIG_VGA_CONSOLE=y -CONFIG_MDA_CONSOLE=m +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y # CONFIG_FONTS is not set @@ -1708,16 +1921,20 @@ CONFIG_SOUND=m # Advanced Linux Sound Architecture # CONFIG_SND=m +CONFIG_SND_VERBOSE_PROCFS=y CONFIG_SND_SEQUENCER=m CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m -CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_RTCTIMER=m # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set -CONFIG_SND_BIT32_EMUL=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set # # Generic devices @@ -1731,34 +1948,8 @@ CONFIG_SND_MPU401=m # # ISA devices # -CONFIG_SND_AD1816A=m -CONFIG_SND_AD1848=m -CONFIG_SND_CS4231=m -CONFIG_SND_CS4232=m -CONFIG_SND_CS4236=m -CONFIG_SND_ES968=m -CONFIG_SND_ES1688=m -CONFIG_SND_ES18XX=m -CONFIG_SND_GUSCLASSIC=m -CONFIG_SND_GUSEXTREME=m -CONFIG_SND_GUSMAX=m -CONFIG_SND_INTERWAVE=m -CONFIG_SND_INTERWAVE_STB=m -CONFIG_SND_OPTI92X_AD1848=m -CONFIG_SND_OPTI92X_CS4231=m -CONFIG_SND_OPTI93X=m -CONFIG_SND_SB8=m -CONFIG_SND_SB16=m -CONFIG_SND_SBAWE=m -CONFIG_SND_SB16_CSP=y +CONFIG_SND_AD1889=m # CONFIG_SND_WAVEFRONT is not set -CONFIG_SND_ALS100=m -CONFIG_SND_AZT2320=m -CONFIG_SND_CMI8330=m -CONFIG_SND_DT019X=m -CONFIG_SND_OPL3SA2=m -CONFIG_SND_SGALAXY=m -CONFIG_SND_SSCAPE=m # # PCI devices @@ -1768,10 +1959,14 @@ CONFIG_SND_AZT3328=m CONFIG_SND_CS46XX=m CONFIG_SND_CS46XX_NEW_DSP=y CONFIG_SND_CS4281=m +CONFIG_SND_CS5535AUDIO=m CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_CA0106=m CONFIG_SND_KORG1212=m CONFIG_SND_NM256=m CONFIG_SND_RME32=m +CONFIG_SND_PCXHR=m CONFIG_SND_RME96=m CONFIG_SND_RME9652=m CONFIG_SND_HDSP=m @@ -1790,28 +1985,36 @@ CONFIG_SND_ICE1724=m CONFIG_SND_INTEL8X0=m CONFIG_SND_SONICVIBES=m CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m CONFIG_SND_VX222=m CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m CONFIG_SND_AU8810=m CONFIG_SND_AU8820=m CONFIG_SND_AU8830=m CONFIG_SND_MIXART=m CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_FM801_TEA575X_BOOL=y CONFIG_SND_INTEL8X0M=m -CONFIG_SND_PDAUDIOCF=m - +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ADLIB=m +CONFIG_SND_MIRO=m +CONFIG_SND_ALS300=m +CONFIG_SND_RIPTIDE=m # # ALSA USB devices # CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m # # PCMCIA devices # # CONFIG_SND_VXPOCKET is not set -# CONFIG_SND_VXP440 is not set # # Open Sound System @@ -1832,6 +2035,7 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set # # USB Host Controller Drivers @@ -1841,11 +2045,13 @@ CONFIG_USB_EHCI_SPLIT_ISO=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_OHCI_HCD=m CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_CS=m # # USB Device Class drivers # -CONFIG_USB_AUDIO=m +# CONFIG_USB_AUDIO is not set +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # # USB Bluetooth TTY can only be used with disabled Bluetooth subsystem @@ -1853,16 +2059,20 @@ CONFIG_USB_AUDIO=m CONFIG_USB_MIDI=m CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m +CONFIG_BLK_DEV_UB=m CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set CONFIG_USB_STORAGE_DATAFAB=y CONFIG_USB_STORAGE_FREECOM=y CONFIG_USB_STORAGE_ISD200=y CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y # # USB Human Interface Devices (HID) @@ -1874,6 +2084,7 @@ CONFIG_HID_PID=y CONFIG_LOGITECH_FF=y CONFIG_THRUSTMASTER_FF=y CONFIG_USB_HIDDEV=y +CONFIG_USB_IDMOUSE=m # # USB HID Boot Protocol drivers @@ -1881,7 +2092,9 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set CONFIG_USB_AIPTEK=m + CONFIG_USB_WACOM=m + CONFIG_USB_KBTAB=m CONFIG_USB_POWERMATE=m CONFIG_USB_XPAD=m @@ -1891,7 +2104,6 @@ CONFIG_USB_XPAD=m # CONFIG_USB_MDC800=m CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m # # USB Multimedia devices @@ -1899,12 +2111,13 @@ CONFIG_USB_HPUSBSCSI=m CONFIG_USB_DABUSB=m CONFIG_USB_VICAM=m CONFIG_USB_DSBR=m +CONFIG_USB_ET61X251=m CONFIG_USB_IBMCAM=m CONFIG_USB_KONICAWC=m CONFIG_USB_OV511=m -CONFIG_USB_PWC=m CONFIG_USB_SE401=m CONFIG_USB_STV680=m +CONFIG_USB_SN9C102=m # # USB Network adaptors @@ -1914,28 +2127,29 @@ CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_USBNET=m +CONFIG_USB_SPEEDTOUCH=m +# Has dumb detection, which gets loaded for every hid device. +# CONFIG_USB_YEALINK is not set +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_NET_ZAURUS=m # # USB Host-to-Host Cables # CONFIG_USB_AN2720=y CONFIG_USB_BELKIN=y -CONFIG_USB_GENESYS=y -CONFIG_USB_NET1080=y -CONFIG_USB_PL2301=y # # Intelligent USB Devices/Gadgets # CONFIG_USB_ARMLINUX=y CONFIG_USB_EPSON2888=y -CONFIG_USB_ZAURUS=y -CONFIG_USB_CDCETHER=y - -# -# USB Network Adapters -# -CONFIG_USB_AX8817X=y # # USB port drivers @@ -1947,15 +2161,24 @@ CONFIG_USB_USS720=m # CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ANYDATA=m +CONFIG_USB_SERIAL_ARK3116=m CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_HP4X=m CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IPW=m CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m CONFIG_USB_SERIAL_KEYSPAN_PDA=m CONFIG_USB_SERIAL_KEYSPAN=m CONFIG_USB_SERIAL_KEYSPAN_MPR=y @@ -1973,13 +2196,17 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y CONFIG_USB_SERIAL_KLSI=m CONFIG_USB_SERIAL_KOBIL_SCT=m CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_OPTION=y +CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_SERIAL_SAFE=m CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_VISOR=m CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_XIRCOM=m + CONFIG_USB_EZUSB=y CONFIG_USB_EMI62=m CONFIG_USB_LED=m @@ -1989,30 +2216,45 @@ CONFIG_USB_G_SERIAL=m # # USB Miscellaneous drivers # -# CONFIG_USB_EMI26 is not set -CONFIG_USB_TIGL=m +CONFIG_USB_EMI26=m CONFIG_USB_AUERSWALD=m CONFIG_USB_RIO500=m -CONFIG_USB_BRLVGER=m CONFIG_USB_LCD=m CONFIG_USB_TEST=m # CONFIG_USB_GADGET is not set # CONFIG_USB_GADGET_PXA2XX is not set # CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_SA1100 is not set CONFIG_USB_ZERO=m CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m +# CONFIG_USB_GADGETFS is not set CONFIG_USB_W9968CF=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_FILE_STORAGE_TEST is not set -CONFIG_USB_MTOUCH=m CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m CONFIG_USB_ALI_M5632=y # CONFIG_USB_CYTHERM is not set -CONFIG_USB_EGALAX=m CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_MON=y +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_ACECAD=m +CONFIG_USB_ATM=m +CONFIG_USB_CXACRU=m +CONFIG_USB_XUSBATM=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_LD=m +CONFIG_USB_APPLETOUCH=m + +CONFIG_USB_TOUCHSCREEN=m + # # File systems @@ -2021,6 +2263,7 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y CONFIG_EXT3_FS=m CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y @@ -2038,6 +2281,7 @@ CONFIG_JFS_FS=m # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y CONFIG_XFS_FS=m # CONFIG_XFS_RT is not set CONFIG_XFS_QUOTA=y @@ -2067,6 +2311,8 @@ CONFIG_UDF_FS=m CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" # CONFIG_NTFS_FS is not set # @@ -2074,13 +2320,11 @@ CONFIG_VFAT_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +CONFIG_DEBUG_FS=y # # Miscellaneous filesystems @@ -2097,8 +2341,9 @@ CONFIG_EFS_FS=m # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=m CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_NAND=y CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_VXFS_FS=m # CONFIG_HPFS_FS is not set CONFIG_QNX4FS_FS=m @@ -2106,16 +2351,20 @@ CONFIG_QNX4FS_FS=m CONFIG_SYSV_FS=m CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set +CONFIG_9P_FS=m +CONFIG_FUSE_FS=m # # Network File Systems # CONFIG_NFS_FS=m CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_DIRECTIO=y CONFIG_NFSD=m CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=m @@ -2124,10 +2373,14 @@ CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_SMB_FS=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set # CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y CONFIG_NCP_FS=m CONFIG_NCPFS_PACKET_SIGNING=y CONFIG_NCPFS_IOCTL_LOCKING=y @@ -2137,18 +2390,21 @@ CONFIG_NCPFS_OS2_NS=y CONFIG_NCPFS_SMALLDOS=y CONFIG_NCPFS_NLS=y CONFIG_NCPFS_EXTRAS=y -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # CONFIG_RXRPC is not set +CONFIG_OCFS2_FS=m +CONFIG_CONFIGFS_FS=m + # # Partition Types # CONFIG_PARTITION_ADVANCED=y # CONFIG_ACORN_PARTITION is not set CONFIG_OSF_PARTITION=y -# CONFIG_AMIGA_PARTITION is not set +CONFIG_AMIGA_PARTITION=y # CONFIG_ATARI_PARTITION is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y @@ -2157,18 +2413,19 @@ CONFIG_MINIX_SUBPARTITION=y CONFIG_SOLARIS_X86_PARTITION=y CONFIG_UNIXWARE_DISKLABEL=y # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set CONFIG_SUN_PARTITION=y CONFIG_EFI_PARTITION=y +CONFIG_KARMA_PARTITION=y + CONFIG_NLS=y # # Native Language Support # CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m CONFIG_NLS_CODEPAGE_850=m @@ -2205,6 +2462,7 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m +CONFIG_NLS_ASCII=y # # Profiling support @@ -2212,46 +2470,54 @@ CONFIG_NLS_UTF8=m CONFIG_PROFILING=y CONFIG_OPROFILE=m -# -# Tux -# -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set - - # # Kernel hacking # CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_HIGHMEM is not set CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_FRAME_POINTER is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_DRIVER is not set +# CONFIG_RCU_TORTURE_TEST is not set +# Turn off these debug options for production kernels. +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_VM=y + +# These debug options are deliberatly left on. +# They aren't that much of a performance impact, and the value +# from getting out-of-tree modules fixed is worth the trade-off. +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +CONFIG_BOOT_DELAY=y +CONFIG_DEBUG_SLAB_LEAK=y + +CONFIG_KGDB=y +# CONFIG_KGDB_CONSOLE is not set +CONFIG_KGDBOE=m +# CONFIG_KGDB_SIMPLE_SERIAL is not set +CONFIG_KGDB_8250_CONF_STRING="" # # Security options # CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y CONFIG_SECURITY_CAPABILITIES=y # CONFIG_SECURITY_ROOTPLUG is not set CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_SECURITY_SELINUX_DEVELOP=y -# CONFIG_SECURITY_SELINUX_MLS is not set -# CONFIG_AUDIT is not set +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SECLVL is not set +CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y # @@ -2262,7 +2528,7 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_DES=m @@ -2278,22 +2544,225 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_TEST is not set CONFIG_LIBCRC32C=m CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_TGR192=m # # Library routines # +CONFIG_CRC16=m CONFIG_CRC32=m +CONFIG_CRC_CCITT=m + CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m -CONFIG_PC=y + +CONFIG_INITRAMFS_SOURCE="" +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +CONFIG_ATA_OVER_ETH=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +CONFIG_NETDUMP=m +CONFIG_DISKDUMP=m + +CONFIG_SCHEDSTATS=y + +CONFIG_TUX=m +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set + +CONFIG_CPUSETS=y +CONFIG_RELAY=y +# CONFIG_SECCOMP is not set +# CONFIG_PRINTK_TIME is not set + +CONFIG_DETECT_SOFTLOCKUP=y + +CONFIG_KEXEC=y + +CONFIG_HWMON=m +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_INOTIFY=y + +CONFIG_CONNECTOR=m + +CONFIG_IBMASR=m + +CONFIG_PM_LEGACY=y + +CONFIG_CRASH=m + +## BEGIN ISA Junk. + +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_PROBE is not set +# CONFIG_LTPC is not set +# CONFIG_COPS is not set + +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_CD_NO_IDESCSI is not set + +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NI52 is not set +# CONFIG_NI65 is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +CONFIG_NET_ISA=y +CONFIG_NE2000=m +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_IBMTR is not set +# CONFIG_SKISA is not set +# CONFIG_PROTEON is not set +# CONFIG_SMCTR is not set +# CONFIG_WAVELAN is not set +# CONFIG_HISAX_16_0 is not set +# CONFIG_HISAX_AVM_A1 is not set +# CONFIG_HISAX_IX1MICROR2 is not set +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set + +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_ATIXL is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set + +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# CONFIG_PCWATCHDOG is not set +# CONFIG_WDT is not set + +# CONFIG_VIDEO_PMS is not set +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set + +# CONFIG_SND_OPL4_LIB is not set +# CONFIG_SND_AD1848_LIB is not set +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_CS4236=m +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +CONFIG_SND_ES18XX=m +# CONFIG_SND_GUS_SYNTH is not set +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_DT019X is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_PDAUDIOCF is not set + +## END of ISA options. + +# FIXME: This needs to be made to depend on PPC +# CONFIG_USB_HIDINPUT_POWERBOOK is not set + +CONFIG_UNWIND_INFO=y +# CONFIG_FORCED_INLINING is not set + +CONFIG_MIGRATION=y +# CONFIG_NEW_LEDS is not set + +CONFIG_UID16=y # CONFIG_X86_PC is not set +CONFIG_X86_GENERICARCH=y # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_NUMAQ is not set # CONFIG_X86_SUMMIT is not set # CONFIG_X86_BIGSMP is not set # CONFIG_X86_VISWS is not set -CONFIG_X86_GENERICARCH=y # CONFIG_X86_ES7000 is not set # CONFIG_M386 is not set # CONFIG_M486 is not set @@ -2327,9 +2796,11 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_GOOD_APIC=y CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_HPET=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y -CONFIG_NR_CPUS=32 +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y CONFIG_X86_TSC=y @@ -2343,32 +2814,41 @@ CONFIG_MICROCODE=m CONFIG_X86_MSR=m CONFIG_X86_CPUID=m CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -CONFIG_HIGHMEM64G=y -# CONFIG_HIGHMEM64G is not set +# CONFIG_NUMA is not set CONFIG_HIGHMEM=y CONFIG_HIGHPTE=y # CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y -CONFIG_HAVE_DEC_LOCK=y -# CONFIG_X86_UP_APIC is not set +CONFIG_X86_UP_APIC=y +CONFIG_X86_UP_IOAPIC=y CONFIG_X86_PM_TIMER=y -CONFIG_X86_4G=y -# CONFIG_EFI is not set +CONFIG_EFI=y +CONFIG_EFI_VARS=y +CONFIG_EFI_PCDP=y +CONFIG_EFI_RTC=y CONFIG_REGPARM=y # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set CONFIG_PCI_GOANY=y -CONFIG_MDA_CONSOLE=m +CONFIG_ROCKETPORT=m CONFIG_SYNCLINK_CS=m CONFIG_SYNCLINK=m CONFIG_SYNCLINKMP=m CONFIG_HP100=m CONFIG_PCMCIA_FDOMAIN=m CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_CRASH=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_CAPI_EICON=y CONFIG_I2O=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m +CONFIG_I2O_CONFIG=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m CONFIG_APM=y # CONFIG_APM_IGNORE_USER_SUSPEND is not set # CONFIG_APM_DO_ENABLE is not set @@ -2379,37 +2859,142 @@ CONFIG_APM_RTC_IS_GMT=y # CONFIG_APM_REAL_MODE_POWER_OFF is not set CONFIG_X86_FIND_SMP_CONFIG=y CONFIG_X86_MPPARSE=y -CONFIG_4KSTACKS=y +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_FAN=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_TOSHIBA=m +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_BLACKLIST_YEAR=1999 +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_IBM=m +CONFIG_PNPACPI=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_X86_ACPI_CPUFREQ=m # CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set -CONFIG_X86_POWERNOW_K6=m +# CONFIG_X86_POWERNOW_K6 is not set CONFIG_X86_POWERNOW_K7=y -CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_POWERNOW_K8=y # CONFIG_X86_GX_SUSPMOD is not set CONFIG_X86_SPEEDSTEP_CENTRINO=y CONFIG_X86_SPEEDSTEP_ICH=y -CONFIG_X86_SPEEDSTEP_SMI=m +CONFIG_X86_SPEEDSTEP_SMI=y CONFIG_X86_SPEEDSTEP_LIB=y CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y # CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set CONFIG_X86_P4_CLOCKMOD=m CONFIG_X86_LONGRUN=y # CONFIG_X86_LONGHAUL is not set +# CONFIG_X86_CPUFREQ_NFORCE2 is not set CONFIG_X86_SMP=y CONFIG_X86_HT=y CONFIG_X86_BIOS_REBOOT=y CONFIG_X86_TRAMPOLINE=y -CONFIG_TUX=m -CONFIG_NVRAM=m +CONFIG_NVRAM=y CONFIG_IBM_ASM=m -CONFIG_M686=y -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM64G=y +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_SCHED_SMT=y +# CONFIG_IRQBALANCE is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_DEBUG=y +CONFIG_PM_STD_PARTITION="" +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_STACK_BACKTRACE_COLS=2 +CONFIG_4KSTACKS=y +CONFIG_KPROBES=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_BIOS=y CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_COMPAQ=m +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_ACPI_IBM_DOCK=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set +# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set +# CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY is not set +CONFIG_PM=y +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW_QOS=y +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +CONFIG_CS5535_GPIO=m +CONFIG_EDAC=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_R82600=m +CONFIG_SCHED_MC=y +CONFIG_SND_ES18XX=m +CONFIG_TCG_INFINEON=m +CONFIG_M686=y +# CONFIG_SMP is not set +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y # CONFIG_HIGHMEM64G is not set -# CONFIG_EWRK3 is not set -CONFIG_NR_CPUS=32 -# CONFIG_X86_PC is not set -CONFIG_X86_GENERICARCH=y diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 3c0a5ba61..847cedb23 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -42,9 +42,9 @@ dev->get_stats: Context: nominally process, but don't sleep inside an rwlock dev->hard_start_xmit: - Synchronization: dev->xmit_lock spinlock. + Synchronization: netif_tx_lock spinlock. When the driver sets NETIF_F_LLTX in dev->features this will be - called without holding xmit_lock. In this case the driver + called without holding netif_tx_lock. In this case the driver has to lock by itself when needed. It is recommended to use a try lock for this and return -1 when the spin lock fails. The locking there should also properly protect against @@ -62,12 +62,12 @@ dev->hard_start_xmit: Only valid when NETIF_F_LLTX is set. dev->tx_timeout: - Synchronization: dev->xmit_lock spinlock. + Synchronization: netif_tx_lock spinlock. Context: BHs disabled Notes: netif_queue_stopped() is guaranteed true dev->set_multicast_list: - Synchronization: dev->xmit_lock spinlock. + Synchronization: netif_tx_lock spinlock. Context: BHs disabled dev->poll: diff --git a/MAINTAINERS b/MAINTAINERS index c3c584240..6a1bb87d8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2572,6 +2572,14 @@ M: dbrownell@users.sourceforge.net L: spi-devel-general@lists.sourceforge.net S: Maintained +STABLE BRANCH: +P: Greg Kroah-Hartman +M: greg@kroah.com +P: Chris Wright +M: chrisw@sous-sol.org +L: stable@kernel.org +S: Maintained + TPM DEVICE DRIVER P: Kylene Hall M: kjhall@us.ibm.com diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 03f53c27e..d75fa4047 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -91,6 +91,15 @@ config X86_PC help Choose this option if your computer is a standard PC or compatible. +config X86_XEN + bool "Xen-compatible" + select X86_UP_APIC if !SMP && XEN_PRIVILEGED_GUEST + select X86_UP_IOAPIC if !SMP && XEN_PRIVILEGED_GUEST + select SWIOTLB + help + Choose this option if you plan to run this kernel on top of the + Xen Hypervisor. + config X86_ELAN bool "AMD Elan" help @@ -193,6 +202,7 @@ source "arch/i386/Kconfig.cpu" config HPET_TIMER bool "HPET Timer Support" + depends on !X86_XEN help This enables the use of the HPET for the kernel's internal timer. HPET is the next generation timer replacing legacy 8254s. @@ -223,7 +233,7 @@ config NR_CPUS config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" - depends on SMP + depends on SMP && !X86_XEN default off help SMT scheduler support improves the CPU scheduler's decision making @@ -233,7 +243,7 @@ config SCHED_SMT config SCHED_MC bool "Multi-core scheduler support" - depends on SMP + depends on SMP && !X86_XEN default y help Multi-core scheduler support improves the CPU scheduler's decision @@ -244,7 +254,7 @@ source "kernel/Kconfig.preempt" config X86_UP_APIC bool "Local APIC support on uniprocessors" - depends on !SMP && !(X86_VISWS || X86_VOYAGER) + depends on !SMP && !(X86_VISWS || X86_VOYAGER || XEN_UNPRIVILEGED_GUEST) help A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU @@ -269,12 +279,12 @@ config X86_UP_IOAPIC config X86_LOCAL_APIC bool - depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) + depends on X86_UP_APIC || ((X86_VISWS || SMP) && !(X86_VOYAGER || XEN_UNPRIVILEGED_GUEST)) default y config X86_IO_APIC bool - depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) + depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER || XEN_UNPRIVILEGED_GUEST)) default y config X86_VISWS_APIC @@ -282,9 +292,14 @@ config X86_VISWS_APIC depends on X86_VISWS default y +config X86_TSC + bool + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ && !X86_XEN + default y + config X86_MCE bool "Machine Check Exception" - depends on !X86_VOYAGER + depends on !(X86_VOYAGER || X86_XEN) ---help--- Machine Check Exception support allows the processor to notify the kernel if it detects a problem (e.g. overheating, component failure). @@ -374,6 +389,7 @@ config X86_REBOOTFIXUPS config MICROCODE tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" + depends on !XEN_UNPRIVILEGED_GUEST ---help--- If you say Y here and also to "/dev file system support" in the 'File systems' section, you will be able to update the microcode on @@ -391,6 +407,7 @@ config MICROCODE config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" + depends on !X86_XEN help This device gives privileged processes access to the x86 Model-Specific Registers (MSRs). It is a character device with @@ -406,6 +423,10 @@ config X86_CPUID with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. +config SWIOTLB + bool + default n + source "drivers/firmware/Kconfig" choice @@ -578,7 +599,7 @@ config HAVE_ARCH_EARLY_PFN_TO_NID config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" - depends on HIGHMEM4G || HIGHMEM64G + depends on (HIGHMEM4G || HIGHMEM64G) && !X86_XEN help The VM uses one page table entry for each page of physical memory. For systems with a lot of RAM, this can be wasteful of precious @@ -587,6 +608,7 @@ config HIGHPTE config MATH_EMULATION bool "Math emulation" + depends on !X86_XEN ---help--- Linux can emulate a math coprocessor (used for floating point operations) if you don't have one. 486DX and Pentium processors have @@ -612,6 +634,8 @@ config MATH_EMULATION config MTRR bool "MTRR (Memory Type Range Register) support" + depends on !XEN_UNPRIVILEGED_GUEST + default y if X86_XEN ---help--- On Intel P6 family processors (Pentium Pro, Pentium II and later) the Memory Type Range Registers (MTRRs) may be used to control @@ -646,7 +670,7 @@ config MTRR config EFI bool "Boot from EFI support (EXPERIMENTAL)" - depends on ACPI + depends on ACPI && !X86_XEN default n ---help--- This enables the the kernel to boot on EFI platforms using @@ -664,7 +688,7 @@ config EFI config IRQBALANCE bool "Enable kernel irq balancing" - depends on SMP && X86_IO_APIC + depends on SMP && X86_IO_APIC && !X86_XEN default y help The default yes will allow the kernel to do irq load balancing. @@ -712,7 +736,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on EXPERIMENTAL && !X86_XEN help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -765,20 +789,25 @@ config HOTPLUG_CPU endmenu +config ARCH_ENABLE_MEMORY_HOTPLUG + def_bool y + depends on HIGHMEM menu "Power management options (ACPI, APM)" - depends on !X86_VOYAGER + depends on !(X86_VOYAGER || XEN_UNPRIVILEGED_GUEST) +if !X86_XEN source kernel/power/Kconfig +endif source "drivers/acpi/Kconfig" menu "APM (Advanced Power Management) BIOS Support" -depends on PM && !X86_VISWS +depends on PM && !(X86_VISWS || X86_XEN) config APM tristate "APM (Advanced Power Management) BIOS support" - depends on PM + depends on PM && PM_LEGACY ---help--- APM is a BIOS specification for saving power using several different techniques. This is mostly useful for battery powered laptops with @@ -963,6 +992,7 @@ choice config PCI_GOBIOS bool "BIOS" + depends on !X86_XEN config PCI_GOMMCONFIG bool "MMConfig" @@ -970,6 +1000,13 @@ config PCI_GOMMCONFIG config PCI_GODIRECT bool "Direct" +config PCI_GOXEN_FE + bool "Xen PCI Frontend" + depends on X86_XEN + help + The PCI device frontend driver allows the kernel to import arbitrary + PCI devices from a PCI backend to support PCI driver domains. + config PCI_GOANY bool "Any" @@ -977,7 +1014,7 @@ endchoice config PCI_BIOS bool - depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY) + depends on !(X86_VISWS || X86_XEN) && PCI && (PCI_GOBIOS || PCI_GOANY) default y config PCI_DIRECT @@ -990,6 +1027,18 @@ config PCI_MMCONFIG depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) default y +config XEN_PCIDEV_FRONTEND + bool + depends on PCI && X86_XEN && (PCI_GOXEN_FE || PCI_GOANY) + default y + +config XEN_PCIDEV_FE_DEBUG + bool "Xen PCI Frontend Debugging" + depends on XEN_PCIDEV_FRONTEND + default n + help + Enables some debug statements within the PCI Frontend. + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" @@ -1000,7 +1049,7 @@ config ISA_DMA_API config ISA bool "ISA support" - depends on !(X86_VOYAGER || X86_VISWS) + depends on !(X86_VOYAGER || X86_VISWS || X86_XEN) help Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff @@ -1027,7 +1076,7 @@ config EISA source "drivers/eisa/Kconfig" config MCA - bool "MCA support" if !(X86_VISWS || X86_VOYAGER) + bool "MCA support" if !(X86_VISWS || X86_VOYAGER || X86_XEN) default y if X86_VOYAGER help MicroChannel Architecture is found in some IBM PS/2 machines and @@ -1091,6 +1140,8 @@ source "security/Kconfig" source "crypto/Kconfig" +source "drivers/xen/Kconfig" + source "lib/Kconfig" # @@ -1116,7 +1167,7 @@ config X86_SMP config X86_HT bool - depends on SMP && !(X86_VISWS || X86_VOYAGER) + depends on SMP && !(X86_VISWS || X86_VOYAGER || X86_XEN) default y config X86_BIOS_REBOOT @@ -1129,6 +1180,16 @@ config X86_TRAMPOLINE depends on X86_SMP || (X86_VOYAGER && SMP) default y +config X86_NO_TSS + bool + depends on X86_XEN + default y + +config X86_NO_IDT + bool + depends on X86_XEN + default y + config KTIME_SCALAR bool default y diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu index eb130482b..f90d8d0df 100644 --- a/arch/i386/Kconfig.cpu +++ b/arch/i386/Kconfig.cpu @@ -251,7 +251,7 @@ config X86_PPRO_FENCE config X86_F00F_BUG bool - depends on M586MMX || M586TSC || M586 || M486 || M386 + depends on (M586MMX || M586TSC || M586 || M486 || M386) && !X86_NO_IDT default y config X86_WP_WORKS_OK diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index c92191b1f..fb28fe741 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -84,6 +84,7 @@ config X86_MPPARSE config DOUBLEFAULT default y bool "Enable doublefault exception handler" if EMBEDDED + depends on !X86_NO_TSS help This option allows trapping of rare doublefault exceptions that would otherwise cause a system to silently reboot. Disabling this diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 94e0fafb4..53b7343aa 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -48,6 +48,11 @@ CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-op CFLAGS += $(cflags-y) +cppflags-$(CONFIG_XEN) += \ + -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) + +CPPFLAGS += $(cppflags-y) + # Default subarch .c files mcore-y := mach-default @@ -71,6 +76,10 @@ mcore-$(CONFIG_X86_BIGSMP) := mach-default mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit mcore-$(CONFIG_X86_SUMMIT) := mach-default +# Xen subarch support +mflags-$(CONFIG_X86_XEN) := -Iinclude/asm-i386/mach-xen +mcore-$(CONFIG_X86_XEN) := mach-xen + # generic subarchitecture mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic mcore-$(CONFIG_X86_GENERICARCH) := mach-default @@ -105,6 +114,19 @@ boot := arch/i386/boot PHONY += zImage bzImage compressed zlilo bzlilo \ zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install +ifdef CONFIG_XEN +CPPFLAGS := -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS) +head-y := arch/i386/kernel/head-xen.o arch/i386/kernel/init_task-xen.o +boot := arch/i386/boot-xen +.PHONY: vmlinuz +all: vmlinuz + +vmlinuz: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $@ + +install: + $(Q)$(MAKE) $(build)=$(boot) XENGUEST=$(XENGUEST) $@ +else all: bzImage # KBUILD_IMAGE specify target image being built @@ -127,6 +149,7 @@ fdimage fdimage144 fdimage288 isoimage: vmlinux install: $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install +endif archclean: $(Q)$(MAKE) $(clean)=arch/i386/boot @@ -145,3 +168,4 @@ endef CLEAN_FILES += arch/$(ARCH)/boot/fdimage \ arch/$(ARCH)/boot/image.iso \ arch/$(ARCH)/boot/mtools.conf +CLEAN_FILES += vmlinuz vmlinux-stripped diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 96fb8a020..ddaa19d89 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -42,6 +42,12 @@ EXTRA_AFLAGS := -traditional obj-$(CONFIG_SCx200) += scx200.o +ifdef CONFIG_XEN +vsyscall_note := vsyscall-note-xen.o +else +vsyscall_note := vsyscall-note.o +endif + # vsyscall.o contains the vsyscall DSO images as __initdata. # We must build both images before we can assemble it. # Note: kbuild does not track this dependency due to usage of .incbin @@ -62,7 +68,7 @@ SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags) $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds \ - $(obj)/vsyscall-%.o $(obj)/vsyscall-note.o FORCE + $(obj)/vsyscall-%.o $(obj)/$(vsyscall_note) FORCE $(call if_changed,syscall) # We also create a special relocatable object that should mirror the symbol @@ -74,5 +80,17 @@ $(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o SYSCFLAGS_vsyscall-syms.o = -r $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \ - $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE + $(obj)/vsyscall-sysenter.o $(obj)/$(vsyscall_note) FORCE $(call if_changed,syscall) + +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen + +obj-y += fixup.o +microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o + +obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) +obj-y := $(call cherrypickxen, $(obj-y)) +extra-y := $(call cherrypickxen, $(extra-y)) +endif diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile index 7e9ac9935..fa783e6f9 100644 --- a/arch/i386/kernel/acpi/Makefile +++ b/arch/i386/kernel/acpi/Makefile @@ -6,3 +6,7 @@ ifneq ($(CONFIG_ACPI_PROCESSOR),) obj-y += cstate.o processor.o endif +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen +obj-y := $(call cherrypickxen, $(obj-y), $(src)) +endif diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c index ac3f4e5ec..c6b52aa8d 100644 --- a/arch/i386/kernel/asm-offsets.c +++ b/arch/i386/kernel/asm-offsets.c @@ -13,6 +13,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -64,10 +65,14 @@ void foo(void) OFFSET(pbe_orig_address, pbe, orig_address); OFFSET(pbe_next, pbe, next); +#ifndef CONFIG_X86_NO_TSS /* Offset from the sysenter stack to tss.esp0 */ - DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, esp0) - + DEFINE(SYSENTER_stack_esp0, offsetof(struct tss_struct, esp0) - sizeof(struct tss_struct)); +#else + /* sysenter stack points directly to esp0 */ + DEFINE(SYSENTER_stack_esp0, 0); +#endif DEFINE(PAGE_SIZE_asm, PAGE_SIZE); - DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL)); } diff --git a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile index 010aecfff..753f1d770 100644 --- a/arch/i386/kernel/cpu/Makefile +++ b/arch/i386/kernel/cpu/Makefile @@ -17,3 +17,8 @@ obj-$(CONFIG_X86_MCE) += mcheck/ obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ + +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen +obj-y := $(call cherrypickxen, $(obj-y), $(src)) +endif diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index da2db31d4..a748409b7 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -581,7 +581,6 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); - /* recalibrate cpu_khz */ recalibrate_cpu_khz(); fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 71fffa174..2ea3c6cac 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -1008,7 +1008,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) * an UP version, and is deprecated by AMD. */ - if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { + if (num_online_cpus() != 1) { printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); kfree(data); return -ENODEV; diff --git a/arch/i386/kernel/cpu/mtrr/Makefile b/arch/i386/kernel/cpu/mtrr/Makefile index a25b701ab..06df4feee 100644 --- a/arch/i386/kernel/cpu/mtrr/Makefile +++ b/arch/i386/kernel/cpu/mtrr/Makefile @@ -3,3 +3,10 @@ obj-y += amd.o obj-y += cyrix.o obj-y += centaur.o +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen +n-obj-xen := generic.o state.o amd.o cyrix.o centaur.o + +obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) +obj-y := $(call cherrypickxen, $(obj-y)) +endif diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 840d990b8..eed41e6dd 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -177,7 +177,7 @@ need_resched: # sysenter call handler stub ENTRY(sysenter_entry) - movl TSS_sysenter_esp0(%esp),%esp + movl SYSENTER_stack_esp0(%esp),%esp sysenter_past_esp: sti pushl $(__USER_DS) @@ -414,7 +414,7 @@ vector=0 ENTRY(irq_entries_start) .rept NR_IRQS ALIGN -1: pushl $vector-256 +1: pushl $~(vector) jmp common_interrupt .data .long 1b @@ -431,7 +431,7 @@ common_interrupt: #define BUILD_INTERRUPT(name, nr) \ ENTRY(name) \ - pushl $nr-256; \ + pushl $~(nr); \ SAVE_ALL \ movl %esp,%eax; \ call smp_/**/name; \ @@ -500,7 +500,7 @@ device_not_available_emulate: * that sets up the real kernel stack. Check here, since we can't * allow the wrong stack to be used. * - * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have + * "SYSENTER_stack_esp0+12" is because the NMI/debug handler will have * already pushed 3 words if it hits on the sysenter instruction: * eflags, cs and eip. * @@ -512,7 +512,7 @@ device_not_available_emulate: cmpw $__KERNEL_CS,4(%esp); \ jne ok; \ label: \ - movl TSS_sysenter_esp0+offset(%esp),%esp; \ + movl SYSENTER_stack_esp0+offset(%esp),%esp; \ pushfl; \ pushl $__KERNEL_CS; \ pushl $sysenter_past_esp diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index f3a9c78c4..2904a6686 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPUS]; */ fastcall unsigned int do_IRQ(struct pt_regs *regs) { - /* high bits used in ret_from_ code */ - int irq = regs->orig_eax & 0xff; + /* high bit used in ret_from_ code */ + int irq = ~regs->orig_eax; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; u32 *isp; diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 4163865dd..d20724297 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -120,14 +120,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), }, }, - { /* HP laptops have weird reboot issues */ - .callback = set_bios_reboot, - .ident = "HP Laptop", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), - }, - }, { } }; diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index ec4959f74..b97719aa4 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -21,10 +22,15 @@ #include #include +#ifdef CONFIG_XEN +#include +#endif + extern asmlinkage void sysenter_entry(void); void enable_sep_cpu(void) { +#ifndef CONFIG_X86_NO_TSS int cpu = get_cpu(); struct tss_struct *tss = &per_cpu(init_tss, cpu); @@ -39,6 +45,7 @@ void enable_sep_cpu(void) wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0); wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); put_cpu(); +#endif } /* @@ -47,7 +54,6 @@ void enable_sep_cpu(void) */ extern const char vsyscall_int80_start, vsyscall_int80_end; extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; - static struct page *sysenter_pages[2]; int __init sysenter_setup(void) @@ -56,16 +62,28 @@ int __init sysenter_setup(void) sysenter_pages[0] = virt_to_page(page); - if (!boot_cpu_has(X86_FEATURE_SEP)) { +#ifdef CONFIG_XEN + if (boot_cpu_has(X86_FEATURE_SEP)) { + struct callback_register sysenter = { + .type = CALLBACKTYPE_sysenter, + .address = { __KERNEL_CS, (unsigned long)sysenter_entry }, + }; + + if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0) + clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability); + } +#endif + + if (boot_cpu_has(X86_FEATURE_SEP)) { memcpy(page, - &vsyscall_int80_start, - &vsyscall_int80_end - &vsyscall_int80_start); + &vsyscall_sysenter_start, + &vsyscall_sysenter_end - &vsyscall_sysenter_start); return 0; } memcpy(page, - &vsyscall_sysenter_start, - &vsyscall_sysenter_end - &vsyscall_sysenter_start); + &vsyscall_int80_start, + &vsyscall_int80_end - &vsyscall_int80_start); return 0; } @@ -130,6 +148,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, return err; } +#ifndef CONFIG_XEN int in_gate_area_no_task(unsigned long addr) { return 0; @@ -144,3 +163,4 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk) { return NULL; } +#endif diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 0b9d741f8..5b65cb842 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -705,18 +705,11 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs) static void io_check_error(unsigned char reason, struct pt_regs * regs) { - unsigned long i; - printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); /* Re-enable the IOCK line, wait for a few seconds */ - reason = (reason & 0xf) | 8; - outb(reason, 0x61); - i = 2000; - while (--i) udelay(1000); - reason &= ~8; - outb(reason, 0x61); + clear_io_check_error(reason); } static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index 00e0118e7..c0adee5da 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -98,7 +98,9 @@ struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs)); struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) { +#ifndef CONFIG_X86_NO_TSS struct tss_struct *tss; +#endif struct pt_regs *ret; unsigned long tmp; @@ -123,12 +125,16 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) do_exit(SIGSEGV); } +#ifndef CONFIG_X86_NO_TSS tss = &per_cpu(init_tss, get_cpu()); +#endif current->thread.esp0 = current->thread.saved_esp0; current->thread.sysenter_cs = __KERNEL_CS; load_esp0(tss, ¤t->thread); current->thread.saved_esp0 = 0; +#ifndef CONFIG_X86_NO_TSS put_cpu(); +#endif loadsegment(fs, current->thread.saved_fs); loadsegment(gs, current->thread.saved_gs); @@ -252,7 +258,9 @@ out: static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk) { +#ifndef CONFIG_X86_NO_TSS struct tss_struct *tss; +#endif long eax; /* * make sure the vm86() system call doesn't try to do anything silly @@ -297,12 +305,16 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk savesegment(fs, tsk->thread.saved_fs); savesegment(gs, tsk->thread.saved_gs); +#ifndef CONFIG_X86_NO_TSS tss = &per_cpu(init_tss, get_cpu()); +#endif tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; if (cpu_has_sep) tsk->thread.sysenter_cs = 0; load_esp0(tss, &tsk->thread); +#ifndef CONFIG_X86_NO_TSS put_cpu(); +#endif tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile index 80908b5aa..2b33b2003 100644 --- a/arch/i386/mm/Makefile +++ b/arch/i386/mm/Makefile @@ -8,3 +8,11 @@ obj-$(CONFIG_NUMA) += discontig.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o + +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen + +obj-y += hypervisor.o + +obj-y := $(call cherrypickxen, $(obj-y)) +endif diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 92c3d9f0e..a00267a5b 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -85,7 +85,7 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) unsigned long flags; set_pte_atomic(kpte, pte); /* change init_mm */ - if (PTRS_PER_PMD > 1) + if (HAVE_SHARED_KERNEL_PMD) return; spin_lock_irqsave(&pgd_lock, flags); diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 2889567e2..de8d18774 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,10 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) __flush_tlb_one(vaddr); } +static int nr_fixmaps = 0; +unsigned long __FIXADDR_TOP = 0xfffff000; +EXPORT_SYMBOL(__FIXADDR_TOP); + void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags) { unsigned long address = __fix_to_virt(idx); @@ -147,6 +152,13 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags) return; } set_pte_pfn(address, phys >> PAGE_SHIFT, flags); + nr_fixmaps++; +} + +void set_fixaddr_top(unsigned long top) +{ + BUG_ON(nr_fixmaps > 0); + __FIXADDR_TOP = top - PAGE_SIZE; } pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) diff --git a/arch/i386/oprofile/Makefile b/arch/i386/oprofile/Makefile index 30f3eb366..e596c39c0 100644 --- a/arch/i386/oprofile/Makefile +++ b/arch/i386/oprofile/Makefile @@ -6,7 +6,11 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) +ifdef CONFIG_XEN +oprofile-y := $(DRIVER_OBJS) xenoprof.o +else oprofile-y := $(DRIVER_OBJS) init.o backtrace.o oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ op_model_ppro.o op_model_p4.o oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o +endif diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile index 62ad75c57..4447f397f 100644 --- a/arch/i386/pci/Makefile +++ b/arch/i386/pci/Makefile @@ -4,6 +4,10 @@ obj-$(CONFIG_PCI_BIOS) += pcbios.o obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o obj-$(CONFIG_PCI_DIRECT) += direct.o +# pcifront should be after pcbios.o, mmconfig.o, and direct.o as it should only +# take over if direct access to the PCI bus is unavailable +obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront.o + pci-y := fixup.o pci-$(CONFIG_ACPI) += acpi.o pci-y += legacy.o irq.o @@ -12,3 +16,8 @@ pci-$(CONFIG_X86_VISWS) := visws.o fixup.o pci-$(CONFIG_X86_NUMAQ) := numa.o irq.o obj-y += $(pci-y) common.o + +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen +obj-y := $(call cherrypickxen, $(obj-y)) +endif diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 6b1ea0c9a..e545b0992 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -15,7 +15,9 @@ #include #include "pci.h" -#define MMCONFIG_APER_SIZE (256*1024*1024) +/* aperture is up to 256MB but BIOS may reserve less */ +#define MMCONFIG_APER_MIN (2 * 1024*1024) +#define MMCONFIG_APER_MAX (256 * 1024*1024) /* Assume systems with more busses have correct MCFG */ #define MAX_CHECK_BUS 16 @@ -197,9 +199,10 @@ void __init pci_mmcfg_init(void) return; if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } diff --git a/arch/i386/power/Makefile b/arch/i386/power/Makefile index 8cfa4e8a7..e74fee667 100644 --- a/arch/i386/power/Makefile +++ b/arch/i386/power/Makefile @@ -1,2 +1,4 @@ -obj-$(CONFIG_PM) += cpu.o +obj-$(CONFIG_PM_LEGACY) += cpu.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += cpu.o +obj-$(CONFIG_ACPI_SLEEP) += cpu.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 67a905304..1e3ad1ecc 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -270,6 +270,9 @@ config HOTPLUG_CPU can be controlled through /sys/devices/system/cpu/cpu#. Say N if you want to disable CPU hotplug. +config ARCH_ENABLE_MEMORY_HOTPLUG + def_bool y + config SCHED_SMT bool "SMT scheduler support" depends on SMP diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index c7b943f10..3edefc8f6 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -164,10 +164,25 @@ sys_pipe (void) return retval; } +int ia64_map_check_rgn(unsigned long addr, unsigned long len, + unsigned long flags) +{ + unsigned long roff; + + /* + * Don't permit mappings into unmapped space, the virtual page table + * of a region, or across a region boundary. Note: RGN_MAP_LIMIT is + * equal to 2^n-PAGE_SIZE (for some integer n <= 61) and len > 0. + */ + roff = REGION_OFFSET(addr); + if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len))) + return -EINVAL; + return 0; +} + static inline unsigned long do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) { - unsigned long roff; struct file *file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); @@ -189,17 +204,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un goto out; } - /* - * Don't permit mappings into unmapped space, the virtual page table of a region, - * or across a region boundary. Note: RGN_MAP_LIMIT is equal to 2^n-PAGE_SIZE - * (for some integer n <= 61) and len > 0. - */ - roff = REGION_OFFSET(addr); - if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len))) { - addr = -EINVAL; - goto out; - } - down_write(¤t->mm->mmap_sem); addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 8255a9be4..7e8a4d1d9 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -279,8 +279,8 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst, return part->reason; } - bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst), - (u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL); + bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt, + (BTE_NORMAL | BTE_WACQUIRE), NULL); if (bte_ret == BTE_SUCCESS) { return xpcSuccess; } diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 1def91fc8..6b5d4c44f 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -1055,6 +1055,8 @@ xpc_do_exit(enum xpc_retval reason) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); } @@ -1215,24 +1217,20 @@ xpc_init(void) partid_t partid; struct xpc_partition *part; pid_t pid; + size_t buf_size; if (!ia64_platform_is("sn2")) { return -ENODEV; } - /* - * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng - * various portions of a partition's reserved page. Its size is based - * on the size of the reserved page header and part_nasids mask. So we - * need to ensure that the other items will fit as well. - */ - if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) { - dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n"); - return -EPERM; - } - DBUG_ON((u64) xpc_remote_copy_buffer != - L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer)); + + buf_size = max(XPC_RP_VARS_SIZE, + XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES); + xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size, + GFP_KERNEL, &xpc_remote_copy_buffer_base); + if (xpc_remote_copy_buffer == NULL) + return -ENOMEM; snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); @@ -1296,6 +1294,8 @@ xpc_init(void) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); return -EBUSY; } @@ -1314,6 +1314,8 @@ xpc_init(void) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); return -EBUSY; } @@ -1365,6 +1367,8 @@ xpc_init(void) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); return -EBUSY; } diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index 2a89cfce4..57c723f5c 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c @@ -71,19 +71,15 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1]; * Generic buffer used to store a local copy of portions of a remote * partition's reserved page (either its header and part_nasids mask, * or its vars). - * - * xpc_discovery runs only once and is a seperate thread that is - * very likely going to be processing in parallel with receiving - * interrupts. */ -char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE + - XP_NASID_MASK_BYTES]; +char *xpc_remote_copy_buffer; +void *xpc_remote_copy_buffer_base; /* * Guarantee that the kmalloc'd memory is cacheline aligned. */ -static void * +void * xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) { /* see if kmalloc will give us cachline aligned memory by default */ @@ -148,7 +144,7 @@ xpc_get_rsvd_page_pa(int nasid) } } - bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len, + bte_res = xp_bte_copy(rp_pa, buf, buf_len, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bte_res != BTE_SUCCESS) { dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res); @@ -447,7 +443,7 @@ xpc_check_remote_hb(void) /* pull the remote_hb cache line */ bres = xp_bte_copy(part->remote_vars_pa, - ia64_tpa((u64) remote_vars), + (u64) remote_vars, XPC_RP_VARS_SIZE, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bres != BTE_SUCCESS) { @@ -498,8 +494,7 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids, /* pull over the reserved page header and part_nasids mask */ - - bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp), + bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp, XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bres != BTE_SUCCESS) { @@ -554,11 +549,8 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars) return xpcVarsNotSet; } - /* pull over the cross partition variables */ - - bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars), - XPC_RP_VARS_SIZE, + bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bres != BTE_SUCCESS) { return xpc_map_bte_errors(bres); @@ -1239,7 +1231,7 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask) part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa); - bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask), + bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask, xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL); return xpc_map_bte_errors(bte_res); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 747025987..f35dd7b70 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -620,6 +620,9 @@ config HOTPLUG_CPU Say N if you are unsure. +config ARCH_ENABLE_MEMORY_HOTPLUG + def_bool y + config KEXEC bool "kexec system call (EXPERIMENTAL)" depends on PPC_MULTIPLATFORM && EXPERIMENTAL diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index b61d86e7c..55f367edd 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -94,6 +94,8 @@ _GLOBAL(__setup_cpu_ppc970) mfspr r0,SPRN_HID0 li r11,5 /* clear DOZE and SLEEP */ rldimi r0,r11,52,8 /* set NAP and DPM */ + li r11,0 + rldimi r0,r11,32,31 /* clear EN_ATTN */ mtspr SPRN_HID0,r0 mfspr r0,SPRN_HID0 mfspr r0,SPRN_HID0 diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 778f22fd8..dbcb85994 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,8 @@ static void crash_kexec_prepare_cpus(void) void default_machine_crash_shutdown(struct pt_regs *regs) { + unsigned int irq; + /* * This function is only called after the system * has paniced or is otherwise in a critical state. @@ -186,6 +189,16 @@ void default_machine_crash_shutdown(struct pt_regs *regs) */ local_irq_disable(); + for_each_irq(irq) { + struct irq_desc *desc = irq_descp(irq); + + if (desc->status & IRQ_INPROGRESS) + desc->handler->end(irq); + + if (!(desc->status & IRQ_DISABLED)) + desc->handler->disable(irq); + } + if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(1, 0); diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 2d60ea30f..9ff7105bc 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -641,23 +641,28 @@ void xics_teardown_cpu(int secondary) ops->cppr_info(cpu, 0x00); iosync(); + /* + * Clear IPI + */ + ops->qirr_info(cpu, 0xff); + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + /* * Some machines need to have at least one cpu in the GIQ, * so leave the master cpu in the group. */ - if (secondary) { - /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? - */ - ops->xirr_info_set(cpu, XICS_IPI); + if (secondary) rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - } + } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 8fa541cc2..5a220d61b 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -220,6 +220,21 @@ out: return err; } +int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) +{ + if (ARCH_SUN4C_SUN4 && + (len > 0x20000000 || + ((flags & MAP_FIXED) && + addr < 0xe0000000 && addr + len > 0x20000000))) + return -EINVAL; + + /* See asm-sparc/uaccess.h */ + if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) + return -EINVAL; + + return 0; +} + /* Linux version of mmap */ static unsigned long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -234,25 +249,13 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len, goto out; } - retval = -EINVAL; len = PAGE_ALIGN(len); - if (ARCH_SUN4C_SUN4 && - (len > 0x20000000 || - ((flags & MAP_FIXED) && - addr < 0xe0000000 && addr + len > 0x20000000))) - goto out_putf; - - /* See asm-sparc/uaccess.h */ - if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) - goto out_putf; - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); -out_putf: if (file) fput(file); out: diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 62d7497fb..ef419255c 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -550,6 +550,26 @@ asmlinkage long sparc64_personality(unsigned long personality) return ret; } +int sparc64_mmap_check(unsigned long addr, unsigned long len, + unsigned long flags) +{ + if (test_thread_flag(TIF_32BIT)) { + if (len >= STACK_TOP32) + return -EINVAL; + + if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len) + return -EINVAL; + } else { + if (len >= VA_EXCLUDE_START) + return -EINVAL; + + if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len)) + return -EINVAL; + } + + return 0; +} + /* Linux version of mmap */ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -565,27 +585,11 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); len = PAGE_ALIGN(len); - retval = -EINVAL; - - if (test_thread_flag(TIF_32BIT)) { - if (len >= STACK_TOP32) - goto out_putf; - - if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len) - goto out_putf; - } else { - if (len >= VA_EXCLUDE_START) - goto out_putf; - - if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len)) - goto out_putf; - } down_write(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); up_write(¤t->mm->mmap_sem); -out_putf: if (file) fput(file); out: diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index 8cb06205d..af9d81db0 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c @@ -69,6 +69,8 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, } else offset += PAGE_SIZE; + if (pte_write(entry)) + entry = pte_mkdirty(entry); do { BUG_ON(!pte_none(*pte)); set_pte_at(mm, address, pte, entry); diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index fc0f0b085..bd4627b4d 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -226,7 +226,7 @@ EXPORT_SYMBOL(physmem_forget_descriptor); EXPORT_SYMBOL(physmem_remove_mapping); EXPORT_SYMBOL(physmem_subst_mapping); -void arch_free_page(struct page *page, int order) +int arch_free_page(struct page *page, int order) { void *virt; int i; @@ -235,6 +235,8 @@ void arch_free_page(struct page *page, int order) virt = __va(page_to_phys(page + i)); physmem_remove_mapping(virt); } + + return 0; } int is_remapped(void *virt) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index b2cd1f245..0f4ed7159 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -123,6 +123,22 @@ config GENERIC_CPU endchoice +config X86_64_XEN + bool "Enable Xen compatible kernel" + select SWIOTLB + help + This option will compile a kernel compatible with Xen hypervisor + +config X86_NO_TSS + bool + depends on X86_64_XEN + default y + +config X86_NO_IDT + bool + depends on X86_64_XEN + default y + # # Define implied options from the CPU selection here # @@ -143,6 +159,7 @@ config X86_INTERNODE_CACHE_BYTES config X86_TSC bool + depends on !X86_64_XEN default y config X86_GOOD_APIC @@ -185,7 +202,7 @@ config X86_CPUID config X86_HT bool - depends on SMP && !MK8 + depends on SMP && !MK8 && !X86_64_XEN default y config MATH_EMULATION @@ -199,14 +216,22 @@ config EISA config X86_IO_APIC bool + depends !XEN_UNPRIVILEGED_GUEST default y +config X86_XEN_GENAPIC + bool + depends X86_64_XEN + default XEN_PRIVILEGED_GUEST || SMP + config X86_LOCAL_APIC bool + depends !XEN_UNPRIVILEGED_GUEST default y config MTRR bool "MTRR (Memory Type Range Register) support" + depends on !XEN_UNPRIVILEGED_GUEST ---help--- On Intel P6 family processors (Pentium Pro, Pentium II and later) the Memory Type Range Registers (MTRRs) may be used to control @@ -247,7 +272,7 @@ config SMP config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" - depends on SMP + depends on SMP && !X86_64_XEN default n help SMT scheduler support improves the CPU scheduler's decision making @@ -257,7 +282,7 @@ config SCHED_SMT config SCHED_MC bool "Multi-core scheduler support" - depends on SMP + depends on SMP && !X86_64_XEN default y help Multi-core scheduler support improves the CPU scheduler's decision @@ -268,7 +293,7 @@ source "kernel/Kconfig.preempt" config NUMA bool "Non Uniform Memory Access (NUMA) Support" - depends on SMP + depends on SMP && !X86_64_XEN help Enable NUMA (Non Uniform Memory Access) support. The kernel will try to allocate memory used by a CPU on the local memory @@ -328,7 +353,7 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on (NUMA || EXPERIMENTAL) + depends on (NUMA || EXPERIMENTAL) && !X86_64_XEN config ARCH_MEMORY_PROBE def_bool y @@ -352,6 +377,7 @@ config NR_CPUS int "Maximum number of CPUs (2-256)" range 2 255 depends on SMP + default "16" if X86_64_XEN default "8" help This allows you to specify the maximum number of CPUs which this @@ -369,9 +395,12 @@ config HOTPLUG_CPU can be controlled through /sys/devices/system/cpu/cpu#. Say N if you want to disable CPU hotplug. +config ARCH_ENABLE_MEMORY_HOTPLUG + def_bool y config HPET_TIMER bool + depends on !X86_64_XEN default y help Use the IA-PC HPET (High Precision Event Timer) to manage @@ -389,7 +418,7 @@ config GART_IOMMU bool "K8 GART IOMMU support" default y select SWIOTLB - depends on PCI + depends on PCI && !X86_64_XEN help Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors and for the bounce buffering software IOMMU. @@ -409,6 +438,7 @@ config SWIOTLB config X86_MCE bool "Machine check support" if EMBEDDED + depends on !X86_64_XEN default y help Include a machine check error handler to report hardware errors. @@ -434,7 +464,7 @@ config X86_MCE_AMD config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on EXPERIMENTAL && !X86_64_XEN help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -525,8 +555,11 @@ config GENERIC_PENDING_IRQ default y menu "Power management options" + depends on !XEN_UNPRIVILEGED_GUEST +if !X86_64_XEN source kernel/power/Kconfig +endif source "drivers/acpi/Kconfig" @@ -549,6 +582,21 @@ config PCI_MMCONFIG bool "Support mmconfig PCI config space access" depends on PCI && ACPI +config XEN_PCIDEV_FRONTEND + bool "Xen PCI Frontend" + depends on PCI && X86_64_XEN + default y + help + The PCI device frontend driver allows the kernel to import arbitrary + PCI devices from a PCI backend to support PCI driver domains. + +config XEN_PCIDEV_FE_DEBUG + bool "Xen PCI Frontend Debugging" + depends on XEN_PCIDEV_FRONTEND + default n + help + Enables some debug statements within the PCI Frontend. + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" @@ -621,4 +669,6 @@ source "security/Kconfig" source "crypto/Kconfig" +source "drivers/xen/Kconfig" + source "lib/Kconfig" diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index e573e2ab5..4b81d9f4c 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -31,6 +31,10 @@ cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) +cppflags-$(CONFIG_XEN) += \ + -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) +CPPFLAGS += $(cppflags-y) + cflags-y += -m64 cflags-y += -mno-red-zone cflags-y += -mcmodel=kernel @@ -72,6 +76,21 @@ boot := arch/x86_64/boot PHONY += bzImage bzlilo install archmrproper \ fdimage fdimage144 fdimage288 isoimage archclean +ifdef CONFIG_XEN +CPPFLAGS := -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS) +head-y := arch/x86_64/kernel/head-xen.o arch/x86_64/kernel/head64-xen.o arch/x86_64/kernel/init_task.o +LDFLAGS_vmlinux := -e _start +boot := arch/i386/boot-xen +.PHONY: vmlinuz +#Default target when executing "make" +all: vmlinuz + +vmlinuz: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $@ + +install: + $(Q)$(MAKE) $(build)=$(boot) XENGUEST=$(XENGUEST) $@ +else #Default target when executing "make" all: bzImage @@ -92,6 +111,7 @@ fdimage fdimage144 fdimage288 isoimage: vmlinux install: $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ +endif archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index e9263b497..a84151e4c 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile @@ -23,9 +23,25 @@ quiet_cmd_syscall = SYSCALL $@ -Wl,-soname=linux-gate.so.1 -o $@ \ -Wl,-T,$(filter-out FORCE,$^) +$(obj)/vsyscall-int80.so \ $(obj)/vsyscall-sysenter.so $(obj)/vsyscall-syscall.so: \ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE $(call if_changed,syscall) -AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32 -AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32 +AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32 -Iarch/i386/kernel +AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32 -Iarch/i386/kernel + +ifdef CONFIG_XEN +AFLAGS_vsyscall-int80.o = -m32 -Wa,-32 -Iarch/i386/kernel +CFLAGS_syscall32-xen.o += -DUSE_INT80 +AFLAGS_syscall32_syscall-xen.o += -DUSE_INT80 + +$(obj)/syscall32_syscall-xen.o: \ + $(foreach F,int80 sysenter syscall,$(obj)/vsyscall-$F.so) + +targets := $(foreach F,int80 sysenter syscall,vsyscall-$F.o vsyscall-$F.so) + +include $(srctree)/scripts/Makefile.xen + +obj-y := $(call cherrypickxen, $(obj-y)) +endif diff --git a/arch/x86_64/ia32/vsyscall-sigreturn.S b/arch/x86_64/ia32/vsyscall-sigreturn.S index 1384367cd..6086ac6fe 100644 --- a/arch/x86_64/ia32/vsyscall-sigreturn.S +++ b/arch/x86_64/ia32/vsyscall-sigreturn.S @@ -139,5 +139,5 @@ __kernel_rt_sigreturn: .align 4 .LENDFDE3: -#include "../../i386/kernel/vsyscall-note.S" +#include diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 059c88313..b0913f3ef 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -20,11 +20,13 @@ obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o +obj-$(CONFIG_X86_XEN_GENAPIC) += genapic.o genapic_xen.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \ genapic.o genapic_cluster.o genapic_flat.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_PM) += suspend.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o +obj-$(CONFIG_ACPI_SLEEP) += suspend.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o @@ -49,3 +51,18 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o quirks-y += ../../i386/kernel/quirks.o i8237-y += ../../i386/kernel/i8237.o msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o + +ifdef CONFIG_XEN +time-y += ../../i386/kernel/time-xen.o +pci-dma-y += ../../i386/kernel/pci-dma-xen.o +microcode-$(subst m,y,$(CONFIG_MICROCODE)) := ../../i386/kernel/microcode-xen.o +quirks-y := ../../i386/kernel/quirks-xen.o + +n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o + +include $(srctree)/scripts/Makefile.xen + +obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) +obj-y := $(call cherrypickxen, $(obj-y)) +extra-y := $(call cherrypickxen, $(extra-y)) +endif diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile index 4fe97071f..aa84f6eb9 100644 --- a/arch/x86_64/kernel/acpi/Makefile +++ b/arch/x86_64/kernel/acpi/Makefile @@ -6,3 +6,4 @@ ifneq ($(CONFIG_ACPI_PROCESSOR),) obj-y += processor.o endif +boot-$(CONFIG_XEN) := ../../../i386/kernel/acpi/boot-xen.o diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c index 38834bbba..06cf05867 100644 --- a/arch/x86_64/kernel/asm-offsets.c +++ b/arch/x86_64/kernel/asm-offsets.c @@ -66,7 +66,9 @@ int main(void) DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); DEFINE(pbe_next, offsetof(struct pbe, next)); +#ifndef CONFIG_X86_NO_TSS BLANK(); DEFINE(TSS_ist, offsetof(struct tss_struct, ist)); +#endif return 0; } diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 586b34c00..4c599eea1 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -596,7 +596,7 @@ retint_kernel: */ .macro apicinterrupt num,func INTR_FRAME - pushq $\num-256 + pushq $~(\num) CFI_ADJUST_CFA_OFFSET 8 interrupt \func jmp ret_from_intr diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c index ce31d904d..9c141e1a6 100644 --- a/arch/x86_64/kernel/init_task.c +++ b/arch/x86_64/kernel/init_task.c @@ -37,6 +37,8 @@ union thread_union init_thread_union struct task_struct init_task = INIT_TASK(init_task); EXPORT_SYMBOL(init_task); + +#ifndef CONFIG_X86_NO_TSS /* * per-CPU TSS segments. Threads are completely 'soft' on Linux, * no more per-task TSS's. The TSS size is kept cacheline-aligned @@ -45,5 +47,6 @@ EXPORT_SYMBOL(init_task); * on exact cacheline boundaries, to eliminate cacheline ping-pong. */ DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; +#endif #define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index d8bd0b345..c87488532 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -91,8 +91,8 @@ skip: */ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) { - /* high bits used in ret_from_ code */ - unsigned irq = regs->orig_rax & 0xff; + /* high bit used in ret_from_ code */ + unsigned irq = ~regs->orig_rax; exit_idle(); irq_enter(); diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c index bf421ed26..07340aecf 100644 --- a/arch/x86_64/kernel/pmtimer.c +++ b/arch/x86_64/kernel/pmtimer.c @@ -60,7 +60,9 @@ int pmtimer_mark_offset(void) delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK); last_pmtmr_tick = tick; +#ifndef CONFIG_XEN monotonic_base += delta * NSEC_PER_USEC; +#endif delta += offset_delay; diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 655b9192e..e8d5f8441 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -1440,7 +1440,7 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; -#ifdef CONFIG_INPUT_PCSPKR +#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE) #include static __init int add_pcspkr(void) { diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 8a691fa6d..189a7372e 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -46,7 +46,7 @@ Control non executable mappings for 64bit processes. on Enable(default) off Disable */ -int __init nonx_setup(char *str) +void __init nonx_setup(const char *str) { if (!strncmp(str, "on", 2)) { __supported_pte_mask |= _PAGE_NX; @@ -55,28 +55,7 @@ int __init nonx_setup(char *str) do_not_nx = 1; __supported_pte_mask &= ~_PAGE_NX; } - return 1; -} -__setup("noexec=", nonx_setup); /* parsed early actually */ - -int force_personality32 = 0; - -/* noexec32=on|off -Control non executable heap for 32bit processes. -To control the stack too use noexec=off - -on PROT_READ does not imply PROT_EXEC for 32bit processes -off PROT_READ implies PROT_EXEC (default) -*/ -static int __init nonx32_setup(char *str) -{ - if (!strcmp(str, "on")) - force_personality32 &= ~READ_IMPLIES_EXEC; - else if (!strcmp(str, "off")) - force_personality32 |= READ_IMPLIES_EXEC; - return 1; } -__setup("noexec32=", nonx32_setup); /* * Great future plan: diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 4a6628b14..e13938d24 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -135,10 +135,10 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) cpu = smp_processor_id(); /* - * orig_rax contains the interrupt vector - 256. + * orig_rax contains the negated interrupt vector. * Use that to determine where the sender put the data. */ - sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START; + sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START; f = &per_cpu(flush_state, sender); if (!cpu_isset(cpu, f->flush_cpumask)) diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile index d25ac86fe..7d6ceaef4 100644 --- a/arch/x86_64/mm/Makefile +++ b/arch/x86_64/mm/Makefile @@ -9,3 +9,13 @@ obj-$(CONFIG_K8_NUMA) += k8topology.o obj-$(CONFIG_ACPI_NUMA) += srat.o hugetlbpage-y = ../../i386/mm/hugetlbpage.o + +ifdef CONFIG_XEN +include $(srctree)/scripts/Makefile.xen + +ioremap-y += ../../i386/mm/ioremap-xen.o +hypervisor-y += ../../i386/mm/hypervisor.o +obj-y += hypervisor.o + +obj-y := $(call cherrypickxen, $(obj-y)) +endif diff --git a/arch/x86_64/oprofile/Makefile b/arch/x86_64/oprofile/Makefile index 6be32683e..589a7966e 100644 --- a/arch/x86_64/oprofile/Makefile +++ b/arch/x86_64/oprofile/Makefile @@ -11,9 +11,12 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) +ifdef CONFIG_XEN +OPROFILE-y := xenoprof.o +else OPROFILE-y := init.o backtrace.o OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o op_model_p4.o \ op_model_ppro.o OPROFILE-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o - +endif oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y)) diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile index a3f6ad570..1ea6ea9b6 100644 --- a/arch/x86_64/pci/Makefile +++ b/arch/x86_64/pci/Makefile @@ -15,11 +15,23 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o obj-$(CONFIG_NUMA) += k8-bus.o +# pcifront should be after mmconfig.o and direct.o as it should only +# take over if direct access to the PCI bus is unavailable +obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront.o + direct-y += ../../i386/pci/direct.o acpi-y += ../../i386/pci/acpi.o +pcifront-y += ../../i386/pci/pcifront.o legacy-y += ../../i386/pci/legacy.o irq-y += ../../i386/pci/irq.o common-y += ../../i386/pci/common.o fixup-y += ../../i386/pci/fixup.o i386-y += ../../i386/pci/i386.o init-y += ../../i386/pci/init.o + +ifdef CONFIG_XEN +irq-y := ../../i386/pci/irq-xen.o +include $(srctree)/scripts/Makefile.xen + +obj-y := $(call cherrypickxen, $(obj-y)) +endif diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index a2060e4d5..3c55c76c6 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c @@ -13,7 +13,10 @@ #include "pci.h" -#define MMCONFIG_APER_SIZE (256*1024*1024) +/* aperture is up to 256MB but BIOS may reserve less */ +#define MMCONFIG_APER_MIN (2 * 1024*1024) +#define MMCONFIG_APER_MAX (256 * 1024*1024) + /* Verify the first 16 busses. We assume that systems with more busses get MCFG right. */ #define MAX_CHECK_BUS 16 @@ -175,9 +178,10 @@ void __init pci_mmcfg_init(void) return; if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } @@ -190,7 +194,8 @@ void __init pci_mmcfg_init(void) } for (i = 0; i < pci_mmcfg_config_num; ++i) { pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; - pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE); + pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, + MMCONFIG_APER_MAX); if (!pci_mmcfg_virt[i].virt) { printk("PCI: Cannot map mmconfig aperture for segment %d\n", pci_mmcfg_config[i].pci_segment_group_number); diff --git a/block/elevator.c b/block/elevator.c index a0afdd317..7be96bbe1 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -766,7 +766,8 @@ void elv_unregister(struct elevator_type *e) read_lock(&tasklist_lock); do_each_thread(g, p) { task_lock(p); - e->ops.trim(p->io_context); + if (p->io_context) + e->ops.trim(p->io_context); task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 7eb36c53f..4293143c9 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -638,7 +638,7 @@ void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) /* Assume anything <= 4GB can be handled by IOMMU. Actually some IOMMUs can handle everything, but I don't know of a way to test this here. */ - if (bounce_pfn < (0xffffffff>>PAGE_SHIFT)) + if (bounce_pfn < (min_t(u64,0xffffffff,BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) dma = 1; q->bounce_pfn = max_low_pfn; #else diff --git a/configs/kernel-2.6.17-i586.config b/configs/kernel-2.6.17-i586.config index 1e12169f5..78c849cc2 100644 --- a/configs/kernel-2.6.17-i586.config +++ b/configs/kernel-2.6.17-i586.config @@ -1,7 +1,8 @@ +# i386 # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-prep -# Thu Jul 27 16:52:11 2006 +# Linux kernel version: 2.6.17.13 +# Wed Oct 18 17:15:50 2006 # CONFIG_X86_32=y CONFIG_SEMAPHORE_SLEEPERS=y @@ -93,6 +94,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # # CONFIG_SMP is not set CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_NUMAQ is not set @@ -152,6 +154,7 @@ CONFIG_X86_MCE=y # CONFIG_MICROCODE is not set CONFIG_X86_MSR=m CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set # # Firmware Drivers @@ -160,10 +163,11 @@ CONFIG_EDD=m CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set -CONFIG_NOHIGHMEM=y -# CONFIG_HIGHMEM4G is not set +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y # CONFIG_HIGHMEM64G is not set CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y @@ -175,6 +179,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_SPARSEMEM_STATIC=y CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_HIGHPTE=y # CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y CONFIG_EFI=y @@ -186,7 +191,9 @@ CONFIG_HZ_250=y # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x400000 +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # # Power management options (ACPI, APM) @@ -279,6 +286,7 @@ CONFIG_PCI=y # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GOMMCONFIG is not set # CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y @@ -1224,7 +1232,10 @@ CONFIG_EL3=m CONFIG_VORTEX=m CONFIG_TYPHOON=m # CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set # CONFIG_NET_VENDOR_RACAL is not set # @@ -1710,7 +1721,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set +CONFIG_SERIO_RAW=m CONFIG_GAMEPORT=m CONFIG_GAMEPORT_NS558=m CONFIG_GAMEPORT_L4=m @@ -2371,6 +2382,7 @@ CONFIG_SND_ENS1371=m CONFIG_SND_ES1938=m CONFIG_SND_ES1968=m CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y CONFIG_SND_FM801_TEA575X=m CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDSP=m @@ -2810,8 +2822,7 @@ CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m CONFIG_RPCSEC_GSS_SPKM3=m -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_SMB_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set CONFIG_CIFS_XATTR=y @@ -2917,6 +2928,7 @@ CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_FS=y diff --git a/configs/kernel-2.6.17-i686-smp.config b/configs/kernel-2.6.17-i686-smp.config index 1be197713..6bbc7950f 100644 --- a/configs/kernel-2.6.17-i686-smp.config +++ b/configs/kernel-2.6.17-i686-smp.config @@ -1,7 +1,8 @@ +# i386 # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-prep -# Thu Jul 27 16:52:13 2006 +# Linux kernel version: 2.6.17.13 +# Wed Oct 18 17:15:52 2006 # CONFIG_X86_32=y CONFIG_SEMAPHORE_SLEEPERS=y @@ -96,6 +97,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_SMP=y # CONFIG_X86_PC is not set +# CONFIG_X86_XEN is not set # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_NUMAQ is not set @@ -163,6 +165,7 @@ CONFIG_I8K=m CONFIG_MICROCODE=m CONFIG_X86_MSR=m CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set # # Firmware Drivers @@ -202,6 +205,7 @@ CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x400000 CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # # Power management options (ACPI, APM) @@ -302,6 +306,7 @@ CONFIG_PCI=y # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GOMMCONFIG is not set # CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y @@ -1362,7 +1367,10 @@ CONFIG_EL3=m CONFIG_VORTEX=m CONFIG_TYPHOON=m # CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set # CONFIG_NET_VENDOR_RACAL is not set # @@ -1844,7 +1852,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set +CONFIG_SERIO_RAW=m CONFIG_GAMEPORT=m CONFIG_GAMEPORT_NS558=m CONFIG_GAMEPORT_L4=m @@ -2570,6 +2578,7 @@ CONFIG_SND_ENS1371=m CONFIG_SND_ES1938=m CONFIG_SND_ES1968=m CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y CONFIG_SND_FM801_TEA575X=m CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDSP=m @@ -3026,8 +3035,7 @@ CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m CONFIG_RPCSEC_GSS_SPKM3=m -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_SMB_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set CONFIG_CIFS_XATTR=y diff --git a/configs/kernel-2.6.17-i686.config b/configs/kernel-2.6.17-i686.config index 97dd34931..111ab3a33 100644 --- a/configs/kernel-2.6.17-i686.config +++ b/configs/kernel-2.6.17-i686.config @@ -1,7 +1,8 @@ +# i386 # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-prep -# Thu Jul 27 16:52:12 2006 +# Linux kernel version: 2.6.17.13 +# Wed Oct 18 17:15:54 2006 # CONFIG_X86_32=y CONFIG_SEMAPHORE_SLEEPERS=y @@ -94,6 +95,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # # CONFIG_SMP is not set CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_NUMAQ is not set @@ -158,6 +160,7 @@ CONFIG_I8K=m CONFIG_MICROCODE=m CONFIG_X86_MSR=m CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set # # Firmware Drivers @@ -196,6 +199,7 @@ CONFIG_HZ=250 CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x400000 +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # # Power management options (ACPI, APM) @@ -294,6 +298,7 @@ CONFIG_PCI=y # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GOMMCONFIG is not set # CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y @@ -1355,7 +1360,10 @@ CONFIG_EL3=m CONFIG_VORTEX=m CONFIG_TYPHOON=m # CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set # CONFIG_NET_VENDOR_RACAL is not set # @@ -1841,7 +1849,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set +CONFIG_SERIO_RAW=m CONFIG_GAMEPORT=m CONFIG_GAMEPORT_NS558=m CONFIG_GAMEPORT_L4=m @@ -2570,6 +2578,7 @@ CONFIG_SND_ENS1371=m CONFIG_SND_ES1938=m CONFIG_SND_ES1968=m CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y CONFIG_SND_FM801_TEA575X=m CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDSP=m @@ -3026,8 +3035,7 @@ CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m CONFIG_RPCSEC_GSS_SPKM3=m -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_SMB_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set CONFIG_CIFS_XATTR=y diff --git a/drivers/Makefile b/drivers/Makefile index 447d8e688..26b29563d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -31,6 +31,7 @@ obj-y += base/ block/ misc/ mfd/ net/ media/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_PPC_PMAC) += macintosh/ +obj-$(CONFIG_XEN) += xen/ obj-$(CONFIG_IDE) += ide/ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index c24652d31..f0c892613 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -46,7 +46,7 @@ if ACPI config ACPI_SLEEP bool "Sleep States" - depends on X86 && (!SMP || SUSPEND_SMP) + depends on X86 && (!SMP || SUSPEND_SMP) && !XEN depends on PM default y ---help--- @@ -300,6 +300,7 @@ config ACPI_SYSTEM config X86_PM_TIMER bool "Power Management Timer Support" if EMBEDDED depends on X86 + depends on !XEN default y help The Power Management Timer is available on all ACPI-capable, diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index a95f636dc..d7791fbc7 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -238,8 +238,9 @@ acpi_evaluate_object(acpi_handle handle, ACPI_ERROR((AE_INFO, "Both Handle and Pathname are NULL")); } else { - ACPI_ERROR((AE_INFO, - "Handle is NULL and Pathname is relative")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", + pathname)); } status = AE_BAD_PARAMETER; diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index fdff774b8..c1434ed11 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -116,8 +116,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, skb = skb_share_check(skb, GFP_ATOMIC); if (skb == NULL) return 0; - if (skb_is_nonlinear(skb)) - if (skb_linearize(skb, GFP_ATOMIC) < 0) + if (skb_linearize(skb)) goto exit; if (!is_aoe_netif(ifp)) goto exit; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 3170eaa25..fdd37e407 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1838,7 +1838,7 @@ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s) init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; cgc.cmd[7] = s->type; - cgc.cmd[9] = cgc.buflen = 0xff; + cgc.cmd[9] = cgc.buflen & 0xff; if ((ret = cdo->generic_packet(cdi, &cgc))) return ret; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 6a7aa9314..418da028c 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -36,6 +36,22 @@ # include #endif +static inline int range_is_allowed(unsigned long from, unsigned long to) +{ + unsigned long cursor; + + cursor = from >> PAGE_SHIFT; + while ((cursor << PAGE_SHIFT) < to) { + if (!devmem_is_allowed(cursor)) { + printk ("Program %s tried to read /dev/mem between %lx->%lx.\n", + current->comm, from, to); + return 0; + } + cursor++; + } + return 1; +} + /* * Architectures vary in how they handle caching for addresses * outside of main memory. @@ -103,22 +119,7 @@ static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size) } #endif -static inline int range_is_allowed(unsigned long from, unsigned long to) -{ - unsigned long cursor; - - cursor = from >> PAGE_SHIFT; - while ((cursor << PAGE_SHIFT) < to) { - if (!devmem_is_allowed(cursor)) { - printk ("Program %s tried to read /dev/mem between %lx->%lx.\n", - current->comm, from, to); - return 0; - } - cursor++; - } - return 1; -} - +#ifndef ARCH_HAS_DEV_MEM /* * This funcion reads the *physical* memory. The f_pos points directly to the * memory location. @@ -245,6 +246,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, *ppos += written; return written; } +#endif #ifndef __HAVE_PHYS_MEM_ACCESS_PROT static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, @@ -681,6 +683,7 @@ static int open_port(struct inode * inode, struct file * filp) #define open_kmem open_mem #define open_oldmem open_mem +#ifndef ARCH_HAS_DEV_MEM static struct file_operations mem_fops = { .llseek = memory_lseek, .read = read_mem, @@ -688,6 +691,9 @@ static struct file_operations mem_fops = { .mmap = mmap_mem, .open = open_mem, }; +#else +extern struct file_operations mem_fops; +#endif static struct file_operations kmem_fops = { .llseek = memory_lseek, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 8ea70625f..2678034be 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -424,6 +424,7 @@ static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs) iowrite32(interrupt, chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); + ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); return IRQ_HANDLED; } diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0b31cf25c..12c15826a 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -133,6 +133,8 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ vt.c for deeply disgusting hack reasons */ DEFINE_MUTEX(tty_mutex); +int console_use_vt = 1; + #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ extern int pty_limit; /* Config limit on Unix98 ptys */ @@ -1674,19 +1676,6 @@ release_mem_out: goto end_init; } -/* - * Get a copy of the termios structure for the driver/index - */ -void tty_get_termios(struct tty_driver *driver, int idx, struct termios *tio) -{ - lock_kernel(); - if (driver->termios[idx]) - *tio = *driver->termios[idx]; - else - *tio = driver->init_termios; - unlock_kernel(); -} - /* * Releases memory associated with a tty structure, and clears out the * driver table slots. @@ -2074,7 +2063,7 @@ retry_open: goto got_driver; } #ifdef CONFIG_VT - if (device == MKDEV(TTY_MAJOR,0)) { + if (console_use_vt && (device == MKDEV(TTY_MAJOR,0))) { extern struct tty_driver *console_driver; driver = console_driver; index = fg_console; @@ -2795,7 +2784,7 @@ static void flush_to_ldisc(void *private_) struct tty_struct *tty = (struct tty_struct *) private_; unsigned long flags; struct tty_ldisc *disc; - struct tty_buffer *tbuf; + struct tty_buffer *tbuf, *head; int count; char *char_buf; unsigned char *flag_buf; @@ -2812,7 +2801,9 @@ static void flush_to_ldisc(void *private_) goto out; } spin_lock_irqsave(&tty->buf.lock, flags); - while((tbuf = tty->buf.head) != NULL) { + head = tty->buf.head; + tty->buf.head = NULL; + while((tbuf = head) != NULL) { while ((count = tbuf->commit - tbuf->read) != 0) { char_buf = tbuf->char_buf_ptr + tbuf->read; flag_buf = tbuf->flag_buf_ptr + tbuf->read; @@ -2821,10 +2812,12 @@ static void flush_to_ldisc(void *private_) disc->receive_buf(tty, char_buf, flag_buf, count); spin_lock_irqsave(&tty->buf.lock, flags); } - if (tbuf->active) + if (tbuf->active) { + tty->buf.head = head; break; - tty->buf.head = tbuf->next; - if (tty->buf.head == NULL) + } + head = tbuf->next; + if (head == NULL) tty->buf.tail = NULL; tty_buffer_free(tty, tbuf); } @@ -3277,6 +3270,8 @@ static int __init tty_init(void) #endif #ifdef CONFIG_VT + if (!console_use_vt) + goto out_vt; cdev_init(&vc0_cdev, &console_fops); if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) @@ -3285,6 +3280,7 @@ static int __init tty_init(void) class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); vty_init(); + out_vt: #endif return 0; } diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 1e371a510..f0dff5ac1 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -8,7 +8,7 @@ menu "Firmware Drivers" config EDD tristate "BIOS Enhanced Disk Drive calls determine boot disk (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on !IA64 + depends on !IA64 && !XEN help Say Y or M here if you want to enable BIOS Enhanced Disk Drive Services real mode BIOS calls to determine which disk diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 766cc969c..9b4f4ee4f 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -181,21 +181,21 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) break; case state_read: - /* Set ACK if receiving the last byte */ - if (iface->len == 1) + /* Set ACK if _next_ byte will be the last one */ + if (iface->len == 2) outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); else outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); - *iface->ptr++ = inb(ACBSDA); - --iface->len; - - if (iface->len == 0) { + if (iface->len == 1) { iface->result = 0; iface->state = state_idle; outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); } + *iface->ptr++ = inb(ACBSDA); + --iface->len; + break; case state_write: @@ -304,8 +304,12 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, buffer = (u8 *)&cur_word; break; - case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: + if (rw == I2C_SMBUS_READ) + data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */ len = data->block[0]; + if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; buffer = &data->block[1]; break; @@ -369,7 +373,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; + I2C_FUNC_SMBUS_I2C_BLOCK; } /* For now, we only handle combined mode (smbus) */ diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 45e2cdf54..2e79137dc 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -756,9 +756,9 @@ int i2c_probe(struct i2c_adapter *adapter, "parameter for adapter %d, " "addr 0x%02x\n", adap_id, address_data->ignore[j + 1]); + ignore = 1; + break; } - ignore = 1; - break; } if (ignore) continue; diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 41d46dbe6..b09a6537c 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ - if (!PCI_DMA_BUS_IS_PHYS) { - addr = BLK_BOUNCE_ANY; - } else if (on && drive->media == ide_disk) { - if (HWIF(drive)->pci_dev) + if (on && drive->media == ide_disk) { + if (!PCI_DMA_BUS_IS_PHYS) + addr = BLK_BOUNCE_ANY; + else if (HWIF(drive)->pci_dev) addr = HWIF(drive)->pci_dev->dma_mask; } diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 3e677c4f8..9914a78a5 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -6,7 +6,7 @@ * * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235, vt8237 + * vt8235, vt8237, vt8237a * * Copyright (c) 2000-2002 Vojtech Pavlik * @@ -82,6 +82,7 @@ static struct via_isa_bridge { { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 8f1292c36..d1788cdf0 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3548,6 +3548,8 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { + pci_save_state(pdev); + #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { struct device_node *of_node; @@ -3559,8 +3561,6 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) } #endif - pci_save_state(pdev); - return 0; } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 5413dc43b..e084dbf76 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2541,6 +2541,9 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) sdev->fix_capacity = 1; + if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */ + (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC)) + sdev->allow_restart = 1; return 0; } diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c index df5e494a9..f4fddd532 100644 --- a/drivers/infiniband/hw/mthca/mthca_reset.c +++ b/drivers/infiniband/hw/mthca/mthca_reset.c @@ -49,6 +49,12 @@ int mthca_reset(struct mthca_dev *mdev) u32 *hca_header = NULL; u32 *bridge_header = NULL; struct pci_dev *bridge = NULL; + int bridge_pcix_cap = 0; + int hca_pcie_cap = 0; + int hca_pcix_cap = 0; + + u16 devctl; + u16 linkctl; #define MTHCA_RESET_OFFSET 0xf0010 #define MTHCA_RESET_VALUE swab32(1) @@ -110,6 +116,9 @@ int mthca_reset(struct mthca_dev *mdev) } } + hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX); + hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); + if (bridge) { bridge_header = kmalloc(256, GFP_KERNEL); if (!bridge_header) { @@ -129,6 +138,13 @@ int mthca_reset(struct mthca_dev *mdev) goto out; } } + bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX); + if (!bridge_pcix_cap) { + err = -ENODEV; + mthca_err(mdev, "Couldn't locate HCA bridge " + "PCI-X capability, aborting.\n"); + goto out; + } } /* actually hit reset */ @@ -178,6 +194,20 @@ int mthca_reset(struct mthca_dev *mdev) good: /* Now restore the PCI headers */ if (bridge) { + if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8, + bridge_header[(bridge_pcix_cap + 0x8) / 4])) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA bridge Upstream " + "split transaction control, aborting.\n"); + goto out; + } + if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc, + bridge_header[(bridge_pcix_cap + 0xc) / 4])) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA bridge Downstream " + "split transaction control, aborting.\n"); + goto out; + } /* * Bridge control register is at 0x3e, so we'll * naturally restore it last in this loop. @@ -203,6 +233,35 @@ good: } } + if (hca_pcix_cap) { + if (pci_write_config_dword(mdev->pdev, hca_pcix_cap, + hca_header[hca_pcix_cap / 4])) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA PCI-X " + "command register, aborting.\n"); + goto out; + } + } + + if (hca_pcie_cap) { + devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4]; + if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL, + devctl)) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA PCI Express " + "Device Control register, aborting.\n"); + goto out; + } + linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4]; + if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL, + linkctl)) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA PCI Express " + "Link control register, aborting.\n"); + goto out; + } + } + for (i = 0; i < 16; ++i) { if (i * 4 == PCI_COMMAND) continue; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 1dae4b238..1d917edcf 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_ptr) ipoib_mcast_stop_thread(dev, 0); - spin_lock_irqsave(&dev->xmit_lock, flags); + local_irq_save(flags); + netif_tx_lock(dev); spin_lock(&priv->lock); /* @@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_ptr) } spin_unlock(&priv->lock); - spin_unlock_irqrestore(&dev->xmit_lock, flags); + netif_tx_unlock(dev); + local_irq_restore(flags); /* We have to cancel outside of the spinlock */ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index cc07bbebb..34a75939a 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -91,7 +91,6 @@ struct pstore { struct dm_snapshot *snap; /* up pointer to my snapshot */ int version; int valid; - uint32_t chunk_size; uint32_t exceptions_per_area; /* @@ -133,7 +132,7 @@ static int alloc_area(struct pstore *ps) int r = -ENOMEM; size_t len; - len = ps->chunk_size << SECTOR_SHIFT; + len = ps->snap->chunk_size << SECTOR_SHIFT; /* * Allocate the chunk_size block of memory that will hold @@ -160,8 +159,8 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw) unsigned long bits; where.bdev = ps->snap->cow->bdev; - where.sector = ps->chunk_size * chunk; - where.count = ps->chunk_size; + where.sector = ps->snap->chunk_size * chunk; + where.count = ps->snap->chunk_size; return dm_io_sync_vm(1, &where, rw, ps->area, &bits); } @@ -188,7 +187,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw) static int zero_area(struct pstore *ps, uint32_t area) { - memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); + memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); return area_io(ps, area, WRITE); } @@ -196,6 +195,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) { int r; struct disk_header *dh; + chunk_t chunk_size; r = chunk_io(ps, 0, READ); if (r) @@ -210,8 +210,29 @@ static int read_header(struct pstore *ps, int *new_snapshot) *new_snapshot = 0; ps->valid = le32_to_cpu(dh->valid); ps->version = le32_to_cpu(dh->version); - ps->chunk_size = le32_to_cpu(dh->chunk_size); - + chunk_size = le32_to_cpu(dh->chunk_size); + if (ps->snap->chunk_size != chunk_size) { + DMWARN("chunk size %llu in device metadata overrides " + "table chunk size of %llu.", + (unsigned long long)chunk_size, + (unsigned long long)ps->snap->chunk_size); + + /* We had a bogus chunk_size. Fix stuff up. */ + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); + free_area(ps); + + ps->snap->chunk_size = chunk_size; + ps->snap->chunk_mask = chunk_size - 1; + ps->snap->chunk_shift = ffs(chunk_size) - 1; + + r = alloc_area(ps); + if (r) + return r; + + r = dm_io_get(sectors_to_pages(chunk_size)); + if (r) + return r; + } } else { DMWARN("Invalid/corrupt snapshot"); r = -ENXIO; @@ -224,13 +245,13 @@ static int write_header(struct pstore *ps) { struct disk_header *dh; - memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); + memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); dh = (struct disk_header *) ps->area; dh->magic = cpu_to_le32(SNAP_MAGIC); dh->valid = cpu_to_le32(ps->valid); dh->version = cpu_to_le32(ps->version); - dh->chunk_size = cpu_to_le32(ps->chunk_size); + dh->chunk_size = cpu_to_le32(ps->snap->chunk_size); return chunk_io(ps, 0, WRITE); } @@ -365,7 +386,7 @@ static void persistent_destroy(struct exception_store *store) { struct pstore *ps = get_info(store); - dm_io_put(sectors_to_pages(ps->chunk_size)); + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); vfree(ps->callbacks); free_area(ps); kfree(ps); @@ -383,6 +404,16 @@ static int persistent_read_metadata(struct exception_store *store) if (r) return r; + /* + * Now we know correct chunk_size, complete the initialisation. + */ + ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) / + sizeof(struct disk_exception); + ps->callbacks = dm_vcalloc(ps->exceptions_per_area, + sizeof(*ps->callbacks)); + if (!ps->callbacks) + return -ENOMEM; + /* * Do we need to setup a new snapshot ? */ @@ -533,9 +564,6 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) ps->snap = store->snap; ps->valid = 1; ps->version = SNAPSHOT_DISK_VERSION; - ps->chunk_size = chunk_size; - ps->exceptions_per_area = (chunk_size << SECTOR_SHIFT) / - sizeof(struct disk_exception); ps->next_free = 2; /* skipping the header and first area */ ps->current_committed = 0; @@ -543,18 +571,9 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) if (r) goto bad; - /* - * Allocate space for all the callbacks. - */ ps->callback_count = 0; atomic_set(&ps->pending_count, 0); - ps->callbacks = dm_vcalloc(ps->exceptions_per_area, - sizeof(*ps->callbacks)); - - if (!ps->callbacks) { - r = -ENOMEM; - goto bad; - } + ps->callbacks = NULL; store->destroy = persistent_destroy; store->read_metadata = persistent_read_metadata; diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 8edd64354..f7e743691 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -102,8 +102,10 @@ static struct hash_cell *__get_name_cell(const char *str) unsigned int h = hash_str(str); list_for_each_entry (hc, _name_buckets + h, name_list) - if (!strcmp(hc->name, str)) + if (!strcmp(hc->name, str)) { + dm_get(hc->md); return hc; + } return NULL; } @@ -114,8 +116,10 @@ static struct hash_cell *__get_uuid_cell(const char *str) unsigned int h = hash_str(str); list_for_each_entry (hc, _uuid_buckets + h, uuid_list) - if (!strcmp(hc->uuid, str)) + if (!strcmp(hc->uuid, str)) { + dm_get(hc->md); return hc; + } return NULL; } @@ -191,7 +195,7 @@ static int unregister_with_devfs(struct hash_cell *hc) */ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) { - struct hash_cell *cell; + struct hash_cell *cell, *hc; /* * Allocate the new cells. @@ -204,14 +208,19 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi * Insert the cell into both hash tables. */ down_write(&_hash_lock); - if (__get_name_cell(name)) + hc = __get_name_cell(name); + if (hc) { + dm_put(hc->md); goto bad; + } list_add(&cell->name_list, _name_buckets + hash_str(name)); if (uuid) { - if (__get_uuid_cell(uuid)) { + hc = __get_uuid_cell(uuid); + if (hc) { list_del(&cell->name_list); + dm_put(hc->md); goto bad; } list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); @@ -289,6 +298,7 @@ static int dm_hash_rename(const char *old, const char *new) if (hc) { DMWARN("asked to rename to an already existing name %s -> %s", old, new); + dm_put(hc->md); up_write(&_hash_lock); kfree(new_name); return -EBUSY; @@ -328,6 +338,7 @@ static int dm_hash_rename(const char *old, const char *new) dm_table_put(table); } + dm_put(hc->md); up_write(&_hash_lock); kfree(old_name); return 0; @@ -611,10 +622,8 @@ static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) return __get_name_cell(param->name); md = dm_get_md(huge_decode_dev(param->dev)); - if (md) { + if (md) mdptr = dm_get_mdptr(md); - dm_put(md); - } return mdptr; } @@ -628,7 +637,6 @@ static struct mapped_device *find_device(struct dm_ioctl *param) hc = __find_device_hash_cell(param); if (hc) { md = hc->md; - dm_get(md); /* * Sneakily write in both the name and the uuid @@ -653,6 +661,7 @@ static struct mapped_device *find_device(struct dm_ioctl *param) static int dev_remove(struct dm_ioctl *param, size_t param_size) { struct hash_cell *hc; + struct mapped_device *md; down_write(&_hash_lock); hc = __find_device_hash_cell(param); @@ -663,8 +672,11 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) return -ENXIO; } + md = hc->md; + __hash_remove(hc); up_write(&_hash_lock); + dm_put(md); param->data_size = 0; return 0; } @@ -790,7 +802,6 @@ static int do_resume(struct dm_ioctl *param) } md = hc->md; - dm_get(md); new_map = hc->new_map; hc->new_map = NULL; @@ -1078,6 +1089,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) { int r; struct hash_cell *hc; + struct mapped_device *md; down_write(&_hash_lock); @@ -1096,7 +1108,9 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) param->flags &= ~DM_INACTIVE_PRESENT_FLAG; r = __dev_status(hc->md, param); + md = hc->md; up_write(&_hash_lock); + dm_put(md); return r; } diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 1816f3067..5af5265cf 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -711,6 +711,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, return -EINVAL; } + m->ti = ti; + r = parse_features(&as, m, ti); if (r) goto bad; @@ -752,7 +754,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, } ti->private = m; - m->ti = ti; return 0; diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d12cf3e5e..2cab46ed1 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -106,12 +106,42 @@ struct region { struct bio_list delayed_bios; }; + +/*----------------------------------------------------------------- + * Mirror set structures. + *---------------------------------------------------------------*/ +struct mirror { + atomic_t error_count; + struct dm_dev *dev; + sector_t offset; +}; + +struct mirror_set { + struct dm_target *ti; + struct list_head list; + struct region_hash rh; + struct kcopyd_client *kcopyd_client; + + spinlock_t lock; /* protects the next two lists */ + struct bio_list reads; + struct bio_list writes; + + /* recovery */ + region_t nr_regions; + int in_sync; + + struct mirror *default_mirror; /* Default mirror */ + + unsigned int nr_mirrors; + struct mirror mirror[0]; +}; + /* * Conversion fns */ static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) { - return bio->bi_sector >> rh->region_shift; + return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift; } static inline sector_t region_to_sector(struct region_hash *rh, region_t region) @@ -223,7 +253,9 @@ static struct region *__rh_alloc(struct region_hash *rh, region_t region) struct region *reg, *nreg; read_unlock(&rh->hash_lock); - nreg = mempool_alloc(rh->region_pool, GFP_NOIO); + nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC); + if (unlikely(!nreg)) + nreg = kmalloc(sizeof(struct region), GFP_NOIO); nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? RH_CLEAN : RH_NOSYNC; nreg->rh = rh; @@ -541,35 +573,6 @@ static void rh_start_recovery(struct region_hash *rh) wake(); } -/*----------------------------------------------------------------- - * Mirror set structures. - *---------------------------------------------------------------*/ -struct mirror { - atomic_t error_count; - struct dm_dev *dev; - sector_t offset; -}; - -struct mirror_set { - struct dm_target *ti; - struct list_head list; - struct region_hash rh; - struct kcopyd_client *kcopyd_client; - - spinlock_t lock; /* protects the next two lists */ - struct bio_list reads; - struct bio_list writes; - - /* recovery */ - region_t nr_regions; - int in_sync; - - struct mirror *default_mirror; /* Default mirror */ - - unsigned int nr_mirrors; - struct mirror mirror[0]; -}; - /* * Every mirror should look like this one. */ @@ -1115,7 +1118,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, struct mirror *m; struct mirror_set *ms = ti->private; - map_context->ll = bio->bi_sector >> ms->rh.region_shift; + map_context->ll = bio_to_region(&ms->rh, bio); if (rw == WRITE) { queue_bio(ms, bio, rw); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 08312b464..b84bc1aae 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -530,7 +530,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) } ti->private = s; - ti->split_io = chunk_size; + ti->split_io = s->chunk_size; return 0; @@ -1204,7 +1204,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, static struct target_type origin_target = { .name = "snapshot-origin", - .version = {1, 1, 0}, + .version = {1, 4, 0}, .module = THIS_MODULE, .ctr = origin_ctr, .dtr = origin_dtr, @@ -1215,7 +1215,7 @@ static struct target_type origin_target = { static struct target_type snapshot_target = { .name = "snapshot", - .version = {1, 1, 0}, + .version = {1, 4, 0}, .module = THIS_MODULE, .ctr = snapshot_ctr, .dtr = snapshot_dtr, diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 4d710b7a1..dfd037858 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -26,6 +26,7 @@ static const char *_name = DM_NAME; static unsigned int major = 0; static unsigned int _major = 0; +static DEFINE_SPINLOCK(_minor_lock); /* * One of these is allocated per bio. */ @@ -54,12 +55,15 @@ union map_info *dm_get_mapinfo(struct bio *bio) return NULL; } +#define MINOR_ALLOCED ((void *)-1) + /* * Bits for the md->flags field. */ #define DMF_BLOCK_IO 0 #define DMF_SUSPENDED 1 #define DMF_FROZEN 2 +#define DMF_FREEING 3 struct mapped_device { struct rw_semaphore io_lock; @@ -218,9 +222,23 @@ static int dm_blk_open(struct inode *inode, struct file *file) { struct mapped_device *md; + spin_lock(&_minor_lock); + md = inode->i_bdev->bd_disk->private_data; + if (!md) + goto out; + + if (test_bit(DMF_FREEING, &md->flags)) { + md = NULL; + goto out; + } + dm_get(md); - return 0; + +out: + spin_unlock(&_minor_lock); + + return md ? 0 : -ENXIO; } static int dm_blk_close(struct inode *inode, struct file *file) @@ -744,14 +762,13 @@ static int dm_any_congested(void *congested_data, int bdi_bits) /*----------------------------------------------------------------- * An IDR is used to keep track of allocated minor numbers. *---------------------------------------------------------------*/ -static DEFINE_MUTEX(_minor_lock); static DEFINE_IDR(_minor_idr); static void free_minor(unsigned int minor) { - mutex_lock(&_minor_lock); + spin_lock(&_minor_lock); idr_remove(&_minor_idr, minor); - mutex_unlock(&_minor_lock); + spin_unlock(&_minor_lock); } /* @@ -764,23 +781,20 @@ static int specific_minor(struct mapped_device *md, unsigned int minor) if (minor >= (1 << MINORBITS)) return -EINVAL; - mutex_lock(&_minor_lock); + r = idr_pre_get(&_minor_idr, GFP_KERNEL); + if (!r) + return -ENOMEM; + + spin_lock(&_minor_lock); if (idr_find(&_minor_idr, minor)) { r = -EBUSY; goto out; } - r = idr_pre_get(&_minor_idr, GFP_KERNEL); - if (!r) { - r = -ENOMEM; - goto out; - } - - r = idr_get_new_above(&_minor_idr, md, minor, &m); - if (r) { + r = idr_get_new_above(&_minor_idr, MINOR_ALLOCED, minor, &m); + if (r) goto out; - } if (m != minor) { idr_remove(&_minor_idr, m); @@ -789,7 +803,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor) } out: - mutex_unlock(&_minor_lock); + spin_unlock(&_minor_lock); return r; } @@ -798,15 +812,13 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor) int r; unsigned int m; - mutex_lock(&_minor_lock); - r = idr_pre_get(&_minor_idr, GFP_KERNEL); - if (!r) { - r = -ENOMEM; - goto out; - } + if (!r) + return -ENOMEM; - r = idr_get_new(&_minor_idr, md, &m); + spin_lock(&_minor_lock); + + r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m); if (r) { goto out; } @@ -820,7 +832,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor) *minor = m; out: - mutex_unlock(&_minor_lock); + spin_unlock(&_minor_lock); return r; } @@ -833,12 +845,16 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) { int r; struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); + void *old_md; if (!md) { DMWARN("unable to allocate device, out of memory."); return NULL; } + if (!try_module_get(THIS_MODULE)) + goto bad0; + /* get a minor number for the dev */ r = persistent ? specific_minor(md, minor) : next_free_minor(md, &minor); if (r < 0) @@ -875,6 +891,10 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) if (!md->disk) goto bad4; + atomic_set(&md->pending, 0); + init_waitqueue_head(&md->wait); + init_waitqueue_head(&md->eventq); + md->disk->major = _major; md->disk->first_minor = minor; md->disk->fops = &dm_blk_dops; @@ -884,9 +904,12 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) add_disk(md->disk); format_dev_t(md->name, MKDEV(_major, minor)); - atomic_set(&md->pending, 0); - init_waitqueue_head(&md->wait); - init_waitqueue_head(&md->eventq); + /* Populate the mapping, nobody knows we exist yet */ + spin_lock(&_minor_lock); + old_md = idr_replace(&_minor_idr, md, minor); + spin_unlock(&_minor_lock); + + BUG_ON(old_md != MINOR_ALLOCED); return md; @@ -898,6 +921,8 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) blk_cleanup_queue(md->queue); free_minor(minor); bad1: + module_put(THIS_MODULE); + bad0: kfree(md); return NULL; } @@ -914,8 +939,14 @@ static void free_dev(struct mapped_device *md) mempool_destroy(md->io_pool); del_gendisk(md->disk); free_minor(minor); + + spin_lock(&_minor_lock); + md->disk->private_data = NULL; + spin_unlock(&_minor_lock); + put_disk(md->disk); blk_cleanup_queue(md->queue); + module_put(THIS_MODULE); kfree(md); } @@ -1015,13 +1046,18 @@ static struct mapped_device *dm_find_md(dev_t dev) if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) return NULL; - mutex_lock(&_minor_lock); + spin_lock(&_minor_lock); md = idr_find(&_minor_idr, minor); - if (!md || (dm_disk(md)->first_minor != minor)) + if (md && (md == MINOR_ALLOCED || + (dm_disk(md)->first_minor != minor) || + test_bit(DMF_FREEING, &md->flags))) { md = NULL; + goto out; + } - mutex_unlock(&_minor_lock); +out: + spin_unlock(&_minor_lock); return md; } @@ -1055,8 +1091,13 @@ void dm_put(struct mapped_device *md) { struct dm_table *map; - if (atomic_dec_and_test(&md->holders)) { + BUG_ON(test_bit(DMF_FREEING, &md->flags)); + + if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { map = dm_get_table(md); + idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor); + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); if (!dm_suspended(md)) { dm_table_presuspend_targets(map); dm_table_postsuspend_targets(map); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4070eff6f..5a5449400 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1486,7 +1486,6 @@ static void raid1d(mddev_t *mddev) d = conf->raid_disks; d--; rdev = conf->mirrors[d].rdev; - atomic_add(s, &rdev->corrected_errors); if (rdev && test_bit(In_sync, &rdev->flags)) { if (sync_page_io(rdev->bdev, @@ -1509,6 +1508,9 @@ static void raid1d(mddev_t *mddev) s<<9, conf->tmppage, READ) == 0) /* Well, this device is dead */ md_error(mddev, rdev); + else + atomic_add(s, &rdev->corrected_errors); + } } } else { diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index ccc7b2eb4..0bcaa358c 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -184,6 +184,11 @@ static struct mt352_config thomson_dtt7579_config = { .pll_set = thomson_dtt7579_pll_set, }; +static struct zl10353_config thomson_dtt7579_zl10353_config = { + .demod_address = 0x0f, + .pll_set = thomson_dtt7579_pll_set, +}; + static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { u32 freq = params->frequency; @@ -617,6 +622,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) switch(type) { case BTTV_BOARD_DVICO_DVBT_LITE: card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); + + if (card->fe == NULL) + card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config, + card->i2c_adapter); + if (card->fe != NULL) { card->fe->ops->info.frequency_min = 174000000; card->fe->ops->info.frequency_max = 862000000; diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 00dd9fa54..e41066ae7 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,6 +37,7 @@ #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" +#include "zl10353.h" struct dvb_bt8xx_card { struct mutex lock; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index a05179016..cb69372fe 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -519,7 +519,9 @@ static int dvb_frontend_thread(void *data) fepriv->delay = 3*HZ; fepriv->status = 0; fepriv->wakeup = 0; - fepriv->reinitialise = 1; + fepriv->reinitialise = 0; + + dvb_frontend_init(fe); while (1) { up(&fepriv->sem); /* is locked when we enter the thread... */ @@ -996,17 +998,17 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) return ret; if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + /* normal tune mode when opened R/W */ + fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; + fepriv->tone = -1; + fepriv->voltage = -1; + ret = dvb_frontend_start (fe); if (ret) dvb_generic_release (inode, file); /* empty event queue */ fepriv->events.eventr = fepriv->events.eventw = 0; - - /* normal tune mode when opened R/W */ - fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; - fepriv->tone = -1; - fepriv->voltage = -1; } return ret; diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 2f0f35811..9fd87521a 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void *data) dvb_net_feed_stop(dev); priv->rx_mode = RX_MODE_UNI; - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); if (dev->flags & IFF_PROMISC) { dprintk("%s: promiscuous mode\n", dev->name); @@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void *data) } } - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); dvb_net_feed_start(dev); } diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 791706ec1..40930a358 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -194,11 +194,11 @@ struct dvb_pll_desc dvb_pll_tda665x = { { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, - { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ }, - { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ }, - { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, - { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ }, + { 444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, + { 793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, + { 444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, } }; EXPORT_SYMBOL(dvb_pll_tda665x); diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 8a7cd7d50..3f4aa083f 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -58,6 +58,7 @@ struct budget_av { struct tasklet_struct ciintf_irq_tasklet; int slot_status; struct dvb_ca_en50221 ca; + u8 reinitialise_demod:1; }; /* GPIO Connections: @@ -214,8 +215,9 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) msleep(100); - /* reinitialise the frontend */ - dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); + /* reinitialise the frontend if necessary */ + if (budget_av->reinitialise_demod) + dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); if (timeout <= 0) { @@ -1017,12 +1019,13 @@ static void frontend_init(struct budget_av *budget_av) struct saa7146_dev * saa = budget_av->budget.dev; struct dvb_frontend * fe = NULL; + /* Enable / PowerON Frontend */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS: - // Enable / PowerON Frontend - saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); break; } @@ -1059,7 +1062,14 @@ static void frontend_init(struct budget_av *budget_av) break; case SUBID_DVBC_KNC1: + budget_av->reinitialise_demod = 1; + fe = tda10021_attach(&philips_cu1216_config, + &budget_av->budget.i2c_adap, + read_pwm(budget_av)); + break; + case SUBID_DVBC_KNC1_PLUS: + budget_av->reinitialise_demod = 1; fe = tda10021_attach(&philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); @@ -1208,11 +1218,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); - - if (!budget_av->has_saa7113) { - ciintf_init(budget_av); - } - + ciintf_init(budget_av); return 0; } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 689e97189..d6d37cf02 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -367,12 +367,6 @@ static void frontend_init(struct budget *budget) // try the ALPS BSRU6 now budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); - if (budget->dvb_frontend) { - budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; - budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; - budget->dvb_frontend->ops->set_tone = budget_set_tone; - break; - } break; case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6b4197018..67d729a84 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -380,10 +380,10 @@ config VIDEO_WM8739 source "drivers/media/video/cx25840/Kconfig" config VIDEO_SAA711X - tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)" - depends on VIDEO_V4L1 && I2C && EXPERIMENTAL + tristate "Philips SAA7113/4/5 video decoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL ---help--- - Old support for the Philips SAA7113/4 video decoders. + Support for the Philips SAA7113/4/5 video decoders. To compile this driver as a module, choose M here: the module will be called saa7115. diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 07476c711..af372dd25 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -2180,7 +2180,6 @@ static struct pci_device_id stradis_pci_tbl[] = { { 0 } }; -MODULE_DEVICE_TABLE(pci, stradis_pci_tbl); static struct pci_driver stradis_driver = { .name = "stradis", diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 066e22b01..365a07494 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -792,7 +792,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; if (dev->features & NETIF_F_TSO) - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 54161aef3..a8f95e511 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1638,7 +1638,7 @@ bnx2_tx_int(struct bnx2 *bp) skb = tx_buf->skb; #ifdef BCM_TSO /* partial BD completions possible with TSO packets */ - if (skb_shinfo(skb)->tso_size) { + if (skb_is_gso(skb)) { u16 last_idx, last_ring_idx; last_idx = sw_cons + @@ -2009,7 +2009,7 @@ bnx2_poll(struct net_device *dev, int *budget) return 1; } -/* Called with rtnl_lock from vlan functions and also dev->xmit_lock +/* Called with rtnl_lock from vlan functions and also netif_tx_lock * from set_multicast. */ static void @@ -4252,7 +4252,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) } #endif -/* Called with dev->xmit_lock. +/* Called with netif_tx_lock. * hard_start_xmit is pseudo-lockless - a lock is only required when * the tx queue is full. This way, we get the benefit of lockless * operations most of the time without the complexities to handle @@ -4290,7 +4290,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } #ifdef BCM_TSO - if ((mss = skb_shinfo(skb)->tso_size) && + if ((mss = skb_shinfo(skb)->gso_size) && (skb->len > (bp->dev->mtu + ETH_HLEN))) { u32 tcp_opt_len, ip_tcp_len; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 55d236726..8171cae06 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1199,8 +1199,7 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) } #define BOND_INTERSECT_FEATURES \ - (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\ - NETIF_F_TSO|NETIF_F_UFO) + (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO) /* * Compute the common dev->feature set available to all slaves. Some @@ -1218,9 +1217,7 @@ static int bond_compute_features(struct bonding *bond) features &= (slave->dev->features & BOND_INTERSECT_FEATURES); if ((features & NETIF_F_SG) && - !(features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) + !(features & NETIF_F_ALL_CSUM)) features &= ~NETIF_F_SG; /* @@ -4191,7 +4188,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) */ bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - /* don't acquire bond device's xmit_lock when + /* don't acquire bond device's netif_tx_lock when * transmitting */ bond_dev->features |= NETIF_F_LLTX; diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 4391bf4bf..722be62f3 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1418,7 +1418,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) struct cpl_tx_pkt *cpl; #ifdef NETIF_F_TSO - if (skb_shinfo(skb)->tso_size) { + if (skb_is_gso(skb)) { int eth_type; struct cpl_tx_pkt_lso *hdr; @@ -1433,7 +1433,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) hdr->ip_hdr_words = skb->nh.iph->ihl; hdr->tcp_hdr_words = skb->h.th->doff; hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type, - skb_shinfo(skb)->tso_size)); + skb_shinfo(skb)->gso_size)); hdr->len = htonl(skb->len - sizeof(*hdr)); cpl = (struct cpl_tx_pkt *)hdr; sge->stats.tx_lso_pkts++; diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 523c2c9fc..c5e702349 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -353,6 +353,7 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82572EI_COPPER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82572EI_SERDES: + case E1000_DEV_ID_82572EI: hw->mac_type = e1000_82572; break; case E1000_DEV_ID_82573E: diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 150e45e30..c01e5d2e5 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -462,6 +462,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F +#define E1000_DEV_ID_82572EI 0x10B9 #define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 97e71a4fe..43e647284 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2413,7 +2413,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, uint8_t ipcss, ipcso, tucss, tucso, hdr_len; int err; - if (skb_shinfo(skb)->tso_size) { + if (skb_is_gso(skb)) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -2421,7 +2421,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, } hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (skb->protocol == ntohs(ETH_P_IP)) { skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; @@ -2538,7 +2538,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, * tso gets written back prematurely before the data is fully * DMA'd to the controller */ if (!skb->data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) { + !skb_is_gso(skb)) { tx_ring->last_tx_tso = 0; size -= 4; } @@ -2776,7 +2776,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; /* The controller does a simple calculation to * make sure there is enough room in the FIFO before * initiating the DMA for each buffer. The calc is: @@ -2825,8 +2825,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) #ifdef NETIF_F_TSO /* Controller Erratum workaround */ - if (!skb->data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) + if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) count++; #endif diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index feb5b223c..1a556957d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -533,9 +533,9 @@ typedef union _ring_type { * critical parts: * - rx is (pseudo-) lockless: it relies on the single-threading provided * by the arch code for interrupts. - * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission + * - tx setup is lockless: it relies on netif_tx_lock. Actual submission * needs dev->priv->lock :-( - * - set_multicast_list: preparation lockless, relies on dev->xmit_lock. + * - set_multicast_list: preparation lockless, relies on netif_tx_lock. */ /* in dev: base, irq */ @@ -1213,7 +1213,7 @@ static void drain_ring(struct net_device *dev) /* * nv_start_xmit: dev->hard_start_xmit function - * Called with dev->xmit_lock held. + * Called with netif_tx_lock held. */ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1303,8 +1303,8 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) np->tx_skbuff[nr] = skb; #ifdef NETIF_F_TSO - if (skb_shinfo(skb)->tso_size) - tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); + if (skb_is_gso(skb)) + tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); else #endif tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); @@ -1407,7 +1407,7 @@ static void nv_tx_done(struct net_device *dev) /* * nv_tx_timeout: dev->tx_timeout function - * Called with dev->xmit_lock held. + * Called with netif_tx_lock held. */ static void nv_tx_timeout(struct net_device *dev) { @@ -1736,8 +1736,8 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) * guessed, there is probably a simpler approach. * Changing the MTU is a rare event, it shouldn't matter. */ - nv_disable_irq(dev); - spin_lock_bh(&dev->xmit_lock); + disable_irq(dev->irq); + netif_tx_lock_bh(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rx(dev); @@ -1768,8 +1768,8 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) nv_start_rx(dev); nv_start_tx(dev); spin_unlock(&np->lock); - spin_unlock_bh(&dev->xmit_lock); - nv_enable_irq(dev); + netif_tx_unlock_bh(dev); + enable_irq(dev->irq); } return 0; } @@ -1803,7 +1803,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr) memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN); if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock_irq(&np->lock); /* stop rx engine */ @@ -1815,7 +1815,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr) /* restart rx engine */ nv_start_rx(dev); spin_unlock_irq(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } else { nv_copy_mac_to_hw(dev); } @@ -1824,7 +1824,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr) /* * nv_set_multicast: dev->set_multicast function - * Called with dev->xmit_lock held. + * Called with netif_tx_lock held. */ static void nv_set_multicast(struct net_device *dev) { diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 102c1f0b9..d12605f0a 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr_ax25 *sa = addr; - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; } @@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, break; } - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); err = 0; break; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index d81a8e1ee..3ebbbe56b 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr_ax25 *sa = addr; - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; } @@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file, break; } - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, addr, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); err = 0; break; diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 31fb2d75d..2e222ef91 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev) dp->st_task_enter++; if ((skb = skb_peek(&dp->tq)) == NULL) { dp->st_txq_refl_try++; - if (spin_trylock(&_dev->xmit_lock)) { + if (netif_tx_trylock(_dev)) { dp->st_rxq_enter++; while ((skb = skb_dequeue(&dp->rq)) != NULL) { skb_queue_tail(&dp->tq, skb); dp->st_rx2tx_tran++; } - spin_unlock(&_dev->xmit_lock); + netif_tx_unlock(_dev); } else { /* reschedule */ dp->st_rxq_notenter++; @@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev) } } - if (spin_trylock(&_dev->xmit_lock)) { + if (netif_tx_trylock(_dev)) { dp->st_rxq_check++; if ((skb = skb_peek(&dp->rq)) == NULL) { dp->tasklet_pending = 0; @@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev) netif_wake_queue(_dev); } else { dp->st_rxq_rsch++; - spin_unlock(&_dev->xmit_lock); + netif_tx_unlock(_dev); goto resched; } - spin_unlock(&_dev->xmit_lock); + netif_tx_unlock(_dev); } else { resched: dp->tasklet_pending = 1; diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 97a49e0be..d70b9e8d6 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) || (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec)) break; udelay(100); - /* must not sleep here - we are called under xmit_lock! */ + /* must not sleep here - called under netif_tx_lock! */ } } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index cfd67d812..83852450a 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1168,7 +1168,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) uint16_t ipcse, tucse, mss; int err; - if(likely(skb_shinfo(skb)->tso_size)) { + if (likely(skb_is_gso(skb))) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -1176,7 +1176,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) } hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b79d6e8d3..997cbce9a 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -74,7 +74,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) struct iphdr *iph = skb->nh.iph; struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4)); unsigned int doffset = (iph->ihl + th->doff) * 4; - unsigned int mtu = skb_shinfo(skb)->tso_size + doffset; + unsigned int mtu = skb_shinfo(skb)->gso_size + doffset; unsigned int offset = 0; u32 seq = ntohl(th->seq); u16 id = ntohs(iph->id); @@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) #endif #ifdef LOOPBACK_TSO - if (skb_shinfo(skb)->tso_size) { + if (skb_is_gso(skb)) { BUG_ON(skb->protocol != htons(ETH_P_IP)); BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 411f4d809..625ff61c9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1200,7 +1200,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (has_tiny_unaligned_frags(skb)) { - if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { + if (__skb_linearize(skb)) { stats->tx_dropped++; printk(KERN_DEBUG "%s: failed to linearize tiny " "unaligned fragment\n", dev->name); diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 90627756d..2e4ecedba 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -318,12 +318,12 @@ performance critical codepaths: The rx process only runs in the interrupt handler. Access from outside the interrupt handler is only permitted after disable_irq(). -The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap +The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap is set, then access is permitted under spin_lock_irq(&np->lock). Thus configuration functions that want to access everything must call disable_irq(dev->irq); - spin_lock_bh(dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock_irq(&np->lock); IV. Notes diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0ad331029..43641dd2c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2171,7 +2171,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) { if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->tso_size; + u32 mss = skb_shinfo(skb)->gso_size; if (mss) return LargeSend | ((mss & MSSMask) << MSSShift); diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 79208f434..0ad01f07e 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3564,8 +3564,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Control_1 = 0; txdp->Control_2 = 0; #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->tso_size; - if (mss) { + mss = skb_shinfo(skb)->gso_size; + if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) { txdp->Control_1 |= TXD_TCP_LSO_EN; txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); } @@ -3585,10 +3585,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; - if (skb_shinfo(skb)->ufo_size) { + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) { int ufo_size; - ufo_size = skb_shinfo(skb)->ufo_size; + ufo_size = skb_shinfo(skb)->gso_size; ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -3614,7 +3614,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -3629,12 +3629,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -3648,7 +3648,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) if (mss) val64 |= TX_FIFO_SPECIAL_FUNC; #endif - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index fba1e4d4d..4103e304f 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.4" +#define DRV_VERSION "1.6.1" #define PFX DRV_NAME " " /* @@ -233,6 +233,8 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) if (hw->ports > 1) reg1 |= PCI_Y2_PHY2_COMA; } + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + udelay(100); if (hw->chip_id == CHIP_ID_YUKON_EC_U) { sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); @@ -243,8 +245,6 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) sky2_pci_write32(hw, PCI_DEV_REG5, 0); } - sky2_pci_write32(hw, PCI_DEV_REG1, reg1); - break; case PCI_D3hot: @@ -321,7 +321,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) } ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - if (hw->copper) { + if (sky2_is_copper(hw)) { if (hw->chip_id == CHIP_ID_YUKON_FE) { /* enable automatic crossover */ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; @@ -338,25 +338,37 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; } } - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); } else { /* workaround for deviation #4.88 (CRC errors) */ /* disable Automatic Crossover */ ctrl &= ~PHY_M_PC_MDIX_MSK; - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + } - if (hw->chip_id == CHIP_ID_YUKON_XL) { - /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - ctrl &= ~PHY_M_MAC_MD_MSK; - ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + /* special setup for PHY 88E1112 Fiber */ + if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) { + pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); + + /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl &= ~PHY_M_MAC_MD_MSK; + ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + if (hw->pmd_type == 'P') { /* select page 1 to access Fiber registers */ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1); + + /* for SFP-module set SIGDET polarity to low */ + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl |= PHY_M_FIB_SIGD_POL; + gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); } + + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); } ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); @@ -373,7 +385,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) adv = PHY_AN_CSMA; if (sky2->autoneg == AUTONEG_ENABLE) { - if (hw->copper) { + if (sky2_is_copper(hw)) { if (sky2->advertising & ADVERTISED_1000baseT_Full) ct1000 |= PHY_M_1000C_AFD; if (sky2->advertising & ADVERTISED_1000baseT_Half) @@ -386,8 +398,12 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) adv |= PHY_M_AN_10_FD; if (sky2->advertising & ADVERTISED_10baseT_Half) adv |= PHY_M_AN_10_HD; - } else /* special defines for FIBER (88E1011S only) */ - adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; + } else { /* special defines for FIBER (88E1040S only) */ + if (sky2->advertising & ADVERTISED_1000baseT_Full) + adv |= PHY_M_AN_1000X_AFD; + if (sky2->advertising & ADVERTISED_1000baseT_Half) + adv |= PHY_M_AN_1000X_AHD; + } /* Set Flow-control capabilities */ if (sky2->tx_pause && sky2->rx_pause) @@ -949,14 +965,14 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) /* * It appears the hardware has a bug in the FIFO logic that * cause it to hang if the FIFO gets overrun and the receive buffer - * is not aligned. ALso alloc_skb() won't align properly if slab + * is not aligned. Also dev_alloc_skb() won't align properly if slab * debugging is enabled. */ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) { struct sk_buff *skb; - skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); + skb = __dev_alloc_skb(size + RX_SKB_ALIGN, gfp_mask); if (likely(skb)) { unsigned long p = (unsigned long) skb->data; skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); @@ -1160,7 +1176,7 @@ static unsigned tx_le_req(const struct sk_buff *skb) count = sizeof(dma_addr_t) / sizeof(u32); count += skb_shinfo(skb)->nr_frags * count; - if (skb_shinfo(skb)->tso_size) + if (skb_is_gso(skb)) ++count; if (skb->ip_summed == CHECKSUM_HW) @@ -1232,7 +1248,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) } /* Check for TCP Segmentation Offload */ - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (mss != 0) { /* just drop the packet if non-linear expansion fails */ if (skb_header_cloned(skb) && @@ -1497,7 +1513,7 @@ static int sky2_down(struct net_device *dev) static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) { - if (!hw->copper) + if (!sky2_is_copper(hw)) return SPEED_1000; if (hw->chip_id == CHIP_ID_YUKON_FE) @@ -1855,7 +1871,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2, goto oversize; if (length < copybreak) { - skb = alloc_skb(length + 2, GFP_ATOMIC); + skb = dev_alloc_skb(length + 2); if (!skb) goto resubmit; @@ -2016,6 +2032,9 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) } } + /* Fully processed status ring so clear irq */ + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + exit_loop: return work_done; } @@ -2187,9 +2206,6 @@ static int sky2_poll(struct net_device *dev0, int *budget) int work_done = 0; u32 status = sky2_read32(hw, B0_Y2_SP_EISR); - if (!~status) - goto out; - if (status & Y2_IS_HW_ERR) sky2_hw_intr(hw); @@ -2221,12 +2237,9 @@ static int sky2_poll(struct net_device *dev0, int *budget) *budget -= work_done; dev0->quota -= work_done; - if (status & Y2_IS_STAT_BMU) - sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - if (sky2_more_work(hw)) return 1; -out: + netif_rx_complete(dev0); sky2_read32(hw, B0_Y2_SP_LISR); @@ -2290,7 +2303,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) static int __devinit sky2_reset(struct sky2_hw *hw) { u16 status; - u8 t8, pmd_type; + u8 t8; int i; sky2_write8(hw, B0_CTST, CS_RST_CLR); @@ -2336,9 +2349,7 @@ static int __devinit sky2_reset(struct sky2_hw *hw) sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); - pmd_type = sky2_read8(hw, B2_PMD_TYP); - hw->copper = !(pmd_type == 'L' || pmd_type == 'S'); - + hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); hw->ports = 1; t8 = sky2_read8(hw, B2_Y2_HW_RES); if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { @@ -2435,21 +2446,22 @@ static int __devinit sky2_reset(struct sky2_hw *hw) static u32 sky2_supported_modes(const struct sky2_hw *hw) { - u32 modes; - if (hw->copper) { - modes = SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_TP; + if (sky2_is_copper(hw)) { + u32 modes = SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_TP; if (hw->chip_id != CHIP_ID_YUKON_FE) modes |= SUPPORTED_1000baseT_Half - | SUPPORTED_1000baseT_Full; + | SUPPORTED_1000baseT_Full; + return modes; } else - modes = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE - | SUPPORTED_Autoneg; - return modes; + return SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg + | SUPPORTED_FIBRE; } static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -2460,7 +2472,7 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->transceiver = XCVR_INTERNAL; ecmd->supported = sky2_supported_modes(hw); ecmd->phy_address = PHY_ADDR_MARV; - if (hw->copper) { + if (sky2_is_copper(hw)) { ecmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half @@ -2469,12 +2481,14 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP; ecmd->port = PORT_TP; - } else + ecmd->speed = sky2->speed; + } else { + ecmd->speed = SPEED_1000; ecmd->port = PORT_FIBRE; + } ecmd->advertising = sky2->advertising; ecmd->autoneg = sky2->autoneg; - ecmd->speed = sky2->speed; ecmd->duplex = sky2->duplex; return 0; } @@ -3187,6 +3201,8 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) struct pci_dev *pdev = hw->pdev; int err; + init_waitqueue_head (&hw->msi_wait); + sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); @@ -3196,10 +3212,8 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) return err; } - init_waitqueue_head (&hw->msi_wait); - sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); - wmb(); + sky2_read8(hw, B0_CTST); wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 8a0bc5525..9516c1f39 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1317,6 +1317,14 @@ enum { PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */ }; +/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ +/***** PHY_MARV_PHY_CTRL (page 1) 16 bit r/w Fiber Specific Ctrl *****/ +enum { + PHY_M_FIB_FORCE_LNK = 1<<10,/* Force Link Good */ + PHY_M_FIB_SIGD_POL = 1<<9, /* SIGDET Polarity */ + PHY_M_FIB_TX_DIS = 1<<3, /* Transmitter Disable */ +}; + /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ /***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/ enum { @@ -1566,7 +1574,7 @@ enum { GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR | GMR_FS_FRAGMENT | GMR_FS_LONG_ERR | - GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | + GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER, }; @@ -1879,7 +1887,7 @@ struct sky2_hw { int pm_cap; u8 chip_id; u8 chip_rev; - u8 copper; + u8 pmd_type; u8 ports; struct sky2_status_le *st_le; @@ -1891,6 +1899,11 @@ struct sky2_hw { wait_queue_head_t msi_wait; }; +static inline int sky2_is_copper(const struct sky2_hw *hw) +{ + return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P'); +} + /* Register accessor for memory mapped device */ static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg) { diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 862c226db..09a6b8e6d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.59" -#define DRV_MODULE_RELDATE "June 8, 2006" +#define DRV_MODULE_VERSION "3.59.1" +#define DRV_MODULE_RELDATE "August 25, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3743,7 +3743,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -3871,7 +3871,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -11381,11 +11381,15 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; } - /* TSO is on by default on chips that support hardware TSO. + /* TSO is on by default on chips that support HW_TSO_2. + * Some HW_TSO_1 capable chips have bugs that can lead to + * tx timeouts in some cases when TSO is enabled. * Firmware TSO on older chips gives lower performance, so it * is off by default, but can be enabled using ethtool. */ - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 && + tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2)) dev->features |= NETIF_F_TSO; #endif diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ff0faab94..cd68f4688 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -125,6 +125,7 @@ #define CHIPREV_ID_5750_A0 0x4000 #define CHIPREV_ID_5750_A1 0x4001 #define CHIPREV_ID_5750_A3 0x4003 +#define CHIPREV_ID_5750_C2 0x4202 #define CHIPREV_ID_5752_A0_HW 0x5000 #define CHIPREV_ID_5752_A0 0x6000 #define CHIPREV_ID_5752_A1 0x6001 diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 136a70c4d..56d86c7c0 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1605,11 +1605,11 @@ static void __devexit w840_remove1 (struct pci_dev *pdev) * - get_stats: * spin_lock_irq(np->lock), doesn't touch hw if not present * - hard_start_xmit: - * netif_stop_queue + spin_unlock_wait(&dev->xmit_lock); + * synchronize_irq + netif_tx_disable; * - tx_timeout: - * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); + * netif_device_detach + netif_tx_disable; * - set_multicast_list - * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); + * netif_device_detach + netif_tx_disable; * - interrupt handler * doesn't touch hw if not present, synchronize_irq waits for * running instances of the interrupt handler. @@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state) netif_device_detach(dev); update_csr6(dev, 0); iowrite32(0, ioaddr + IntrEnable); - netif_stop_queue(dev); spin_unlock_irq(&np->lock); - spin_unlock_wait(&dev->xmit_lock); synchronize_irq(dev->irq); + netif_tx_disable(dev); np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index d9258d420..389d19fb5 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -340,7 +340,7 @@ enum state_values { #endif #if defined(NETIF_F_TSO) -#define skb_tso_size(x) (skb_shinfo(x)->tso_size) +#define skb_tso_size(x) (skb_shinfo(x)->gso_size) #define TSO_NUM_DESCRIPTORS 2 #define TSO_OFFLOAD_ON TYPHOON_OFFLOAD_TCP_SEGMENT #else @@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) * If problems develop with TSO, check this first. */ numDesc = skb_shinfo(skb)->nr_frags + 1; - if(skb_tso_size(skb)) + if (skb_is_gso(skb)) numDesc++; /* When checking for free space in the ring, we need to also @@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) TYPHOON_TX_PF_VLAN_TAG_SHIFT); } - if(skb_tso_size(skb)) { + if (skb_is_gso(skb)) { first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT; first_txd->numDesc++; diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index ed1f837c8..09e05fe40 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -248,6 +248,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr); static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *); static int velocity_soft_reset(struct velocity_info *vptr); static void mii_init(struct velocity_info *vptr, u32 mii_status); +static u32 velocity_get_link(struct net_device *dev); static u32 velocity_get_opt_media_mode(struct velocity_info *vptr); static void velocity_print_link_status(struct velocity_info *vptr); static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs); @@ -798,6 +799,9 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi if (ret < 0) goto err_iounmap; + if (velocity_get_link(dev)) + netif_carrier_off(dev); + velocity_print_info(vptr); pci_set_drvdata(pdev, dev); @@ -1653,8 +1657,10 @@ static void velocity_error(struct velocity_info *vptr, int status) if (linked) { vptr->mii_status &= ~VELOCITY_LINK_FAIL; + netif_carrier_on(vptr->dev); } else { vptr->mii_status |= VELOCITY_LINK_FAIL; + netif_carrier_off(vptr->dev); } velocity_print_link_status(vptr); @@ -1899,6 +1905,13 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) int pktlen = skb->len; +#ifdef VELOCITY_ZERO_COPY_SUPPORT + if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) { + kfree_skb(skb); + return 0; + } +#endif + spin_lock_irqsave(&vptr->lock, flags); index = vptr->td_curr[qnum]; @@ -1914,8 +1927,6 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) */ if (pktlen < ETH_ZLEN) { /* Cannot occur until ZC support */ - if(skb_linearize(skb, GFP_ATOMIC)) - return 0; pktlen = ETH_ZLEN; memcpy(tdinfo->buf, skb->data, skb->len); memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len); @@ -1933,7 +1944,6 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) int nfrags = skb_shinfo(skb)->nr_frags; tdinfo->skb = skb; if (nfrags > 6) { - skb_linearize(skb, GFP_ATOMIC); memcpy(tdinfo->buf, skb->data, skb->len); tdinfo->skb_dma[0] = tdinfo->buf_dma; td_ptr->tdesc0.pktsize = diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index c2d0b09e0..a5fcfcde6 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -1833,7 +1833,9 @@ static int __orinoco_program_rids(struct net_device *dev) /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->mc_count = 0; - __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ + + /* FIXME: what about netif_tx_lock */ + __orinoco_set_multicast_list(dev); return 0; } diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index f7b77ce54..54fe4e4ea 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -245,7 +245,7 @@ spectrum_reset(struct pcmcia_device *link, int idle) u_int save_cor; /* Doing it if hardware is gone is guaranteed crash */ - if (pcmcia_dev_present(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; /* Save original COR value */ diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index b2e8e49c8..a647d3982 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -6,6 +6,10 @@ * * @author John Levon * + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. + * * This is the core of the buffer management. Each * CPU buffer is processed and entered into the * global event buffer. Such processing is necessary @@ -275,15 +279,31 @@ static void add_cpu_switch(int i) last_cookie = INVALID_COOKIE; } -static void add_kernel_ctx_switch(unsigned int in_kernel) +static void add_cpu_mode_switch(unsigned int cpu_mode) { add_event_entry(ESCAPE_CODE); - if (in_kernel) - add_event_entry(KERNEL_ENTER_SWITCH_CODE); - else - add_event_entry(KERNEL_EXIT_SWITCH_CODE); + switch (cpu_mode) { + case CPU_MODE_USER: + add_event_entry(USER_ENTER_SWITCH_CODE); + break; + case CPU_MODE_KERNEL: + add_event_entry(KERNEL_ENTER_SWITCH_CODE); + break; + case CPU_MODE_XEN: + add_event_entry(XEN_ENTER_SWITCH_CODE); + break; + default: + break; + } } - + +static void add_domain_switch(unsigned long domain_id) +{ + add_event_entry(ESCAPE_CODE); + add_event_entry(DOMAIN_SWITCH_CODE); + add_event_entry(domain_id); +} + static void add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) { @@ -348,9 +368,9 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s) * for later lookup from userspace. */ static int -add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel) +add_sample(struct mm_struct * mm, struct op_sample * s, int cpu_mode) { - if (in_kernel) { + if (cpu_mode >= CPU_MODE_KERNEL) { add_sample_entry(s->eip, s->event); return 1; } else if (mm) { @@ -496,10 +516,11 @@ void sync_buffer(int cpu) struct mm_struct *mm = NULL; struct task_struct * new; unsigned long cookie = 0; - int in_kernel = 1; + int cpu_mode = 1; unsigned int i; sync_buffer_state state = sb_buffer_start; unsigned long available; + int domain_switch = 0; down(&buffer_sem); @@ -512,16 +533,18 @@ void sync_buffer(int cpu) for (i = 0; i < available; ++i) { struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; - if (is_code(s->eip)) { - if (s->event <= CPU_IS_KERNEL) { - /* kernel/userspace switch */ - in_kernel = s->event; + if (is_code(s->eip) && !domain_switch) { + if (s->event <= CPU_MODE_XEN) { + /* xen/kernel/userspace switch */ + cpu_mode = s->event; if (state == sb_buffer_start) state = sb_sample_start; - add_kernel_ctx_switch(s->event); + add_cpu_mode_switch(s->event); } else if (s->event == CPU_TRACE_BEGIN) { state = sb_bt_start; add_trace_begin(); + } else if (s->event == CPU_DOMAIN_SWITCH) { + domain_switch = 1; } else { struct mm_struct * oldmm = mm; @@ -535,11 +558,16 @@ void sync_buffer(int cpu) add_user_ctx_switch(new, cookie); } } else { - if (state >= sb_bt_start && - !add_sample(mm, s, in_kernel)) { - if (state == sb_bt_start) { - state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); + if (domain_switch) { + add_domain_switch(s->eip); + domain_switch = 0; + } else { + if (state >= sb_bt_start && + !add_sample(mm, s, cpu_mode)) { + if (state == sb_bt_start) { + state = sb_bt_ignore; + atomic_inc(&oprofile_stats.bt_lost_no_mapping); + } } } } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index fc4bc9b94..a59878e14 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -6,6 +6,10 @@ * * @author John Levon * + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. + * * Each CPU has a local buffer that stores PC value/event * pairs. We also log context switches when we notice them. * Eventually each CPU's buffer is processed into the global @@ -34,6 +38,8 @@ static void wq_sync_buffer(void *); #define DEFAULT_TIMER_EXPIRE (HZ / 10) static int work_enabled; +static int32_t current_domain = COORDINATOR_DOMAIN; + void free_cpu_buffers(void) { int i; @@ -57,7 +63,7 @@ int alloc_cpu_buffers(void) goto fail; b->last_task = NULL; - b->last_is_kernel = -1; + b->last_cpu_mode = -1; b->tracing = 0; b->buffer_size = buffer_size; b->tail_pos = 0; @@ -113,7 +119,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf) * collected will populate the buffer with proper * values to initialize the buffer */ - cpu_buf->last_is_kernel = -1; + cpu_buf->last_cpu_mode = -1; cpu_buf->last_task = NULL; } @@ -163,13 +169,13 @@ add_code(struct oprofile_cpu_buffer * buffer, unsigned long value) * because of the head/tail separation of the writer and reader * of the CPU buffer. * - * is_kernel is needed because on some architectures you cannot + * cpu_mode is needed because on some architectures you cannot * tell if you are in kernel or user space simply by looking at - * pc. We tag this in the buffer by generating kernel enter/exit - * events whenever is_kernel changes + * pc. We tag this in the buffer by generating kernel/user (and xen) + * enter events whenever cpu_mode changes */ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, - int is_kernel, unsigned long event) + int cpu_mode, unsigned long event) { struct task_struct * task; @@ -180,18 +186,20 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, return 0; } - is_kernel = !!is_kernel; + WARN_ON(cpu_mode > CPU_MODE_XEN); task = current; /* notice a switch from user->kernel or vice versa */ - if (cpu_buf->last_is_kernel != is_kernel) { - cpu_buf->last_is_kernel = is_kernel; - add_code(cpu_buf, is_kernel); + if (cpu_buf->last_cpu_mode != cpu_mode) { + cpu_buf->last_cpu_mode = cpu_mode; + add_code(cpu_buf, cpu_mode); } - + /* notice a task switch */ - if (cpu_buf->last_task != task) { + /* if not processing other domain samples */ + if ((cpu_buf->last_task != task) && + (current_domain == COORDINATOR_DOMAIN)) { cpu_buf->last_task = task; add_code(cpu_buf, (unsigned long)task); } @@ -275,6 +283,25 @@ void oprofile_add_trace(unsigned long pc) add_sample(cpu_buf, pc, 0); } +int oprofile_add_domain_switch(int32_t domain_id) +{ + struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; + + /* should have space for switching into and out of domain + (2 slots each) plus one sample and one cpu mode switch */ + if (((nr_available_slots(cpu_buf) < 6) && + (domain_id != COORDINATOR_DOMAIN)) || + (nr_available_slots(cpu_buf) < 2)) + return 0; + + add_code(cpu_buf, CPU_DOMAIN_SWITCH); + add_sample(cpu_buf, domain_id, 0); + + current_domain = domain_id; + + return 1; +} + /* * This serves to avoid cpu buffer overflow, and makes sure * the task mortuary progresses diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 09abb80e0..cd94735be 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -36,7 +36,7 @@ struct oprofile_cpu_buffer { volatile unsigned long tail_pos; unsigned long buffer_size; struct task_struct * last_task; - int last_is_kernel; + int last_cpu_mode; int tracing; struct op_sample * buffer; unsigned long sample_received; @@ -51,7 +51,10 @@ extern struct oprofile_cpu_buffer cpu_buffer[]; void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); /* transient events for the CPU buffer -> event buffer */ -#define CPU_IS_KERNEL 1 -#define CPU_TRACE_BEGIN 2 +#define CPU_MODE_USER 0 +#define CPU_MODE_KERNEL 1 +#define CPU_MODE_XEN 2 +#define CPU_TRACE_BEGIN 3 +#define CPU_DOMAIN_SWITCH 4 #endif /* OPROFILE_CPU_BUFFER_H */ diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h index 018023630..0c33ee71e 100644 --- a/drivers/oprofile/event_buffer.h +++ b/drivers/oprofile/event_buffer.h @@ -29,15 +29,20 @@ void wake_up_buffer_waiter(void); #define CPU_SWITCH_CODE 2 #define COOKIE_SWITCH_CODE 3 #define KERNEL_ENTER_SWITCH_CODE 4 -#define KERNEL_EXIT_SWITCH_CODE 5 +#define USER_ENTER_SWITCH_CODE 5 #define MODULE_LOADED_CODE 6 #define CTX_TGID_CODE 7 #define TRACE_BEGIN_CODE 8 #define TRACE_END_CODE 9 +#define XEN_ENTER_SWITCH_CODE 10 +#define DOMAIN_SWITCH_CODE 11 #define INVALID_COOKIE ~0UL #define NO_COOKIE 0UL +/* Constant used to refer to coordinator domain (Xen) */ +#define COORDINATOR_DOMAIN -1 + /* add data to the event buffer */ void add_event_entry(unsigned long data); diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index b3f1cd6a2..76bac8dfe 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -5,6 +5,10 @@ * @remark Read the file COPYING * * @author John Levon + * + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #include @@ -19,7 +23,7 @@ #include "cpu_buffer.h" #include "buffer_sync.h" #include "oprofile_stats.h" - + struct oprofile_operations oprofile_ops; unsigned long oprofile_started; @@ -33,6 +37,34 @@ static DECLARE_MUTEX(start_sem); */ static int timer = 0; +#ifdef CONFIG_XEN +int oprofile_set_active(int active_domains[], unsigned int adomains) +{ + int err; + + if (!oprofile_ops.set_active) + return -EINVAL; + + down(&start_sem); + err = oprofile_ops.set_active(active_domains, adomains); + up(&start_sem); + return err; +} + +int oprofile_set_passive(int passive_domains[], unsigned int pdomains) +{ + int err; + + if (!oprofile_ops.set_passive) + return -EINVAL; + + down(&start_sem); + err = oprofile_ops.set_passive(passive_domains, pdomains); + up(&start_sem); + return err; +} +#endif + int oprofile_setup(void) { int err; diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index 183236508..587db2b0a 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h @@ -35,5 +35,10 @@ void oprofile_create_files(struct super_block * sb, struct dentry * root); void oprofile_timer_init(struct oprofile_operations * ops); int oprofile_set_backtrace(unsigned long depth); - + +#ifdef CONFIG_XEN +int oprofile_set_active(int active_domains[], unsigned int adomains); +int oprofile_set_passive(int passive_domains[], unsigned int pdomains); +#endif + #endif /* OPROF_H */ diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index a72006c08..388846526 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c @@ -5,15 +5,21 @@ * @remark Read the file COPYING * * @author John Levon + * + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #include #include +#include +#include #include "event_buffer.h" #include "oprofile_stats.h" #include "oprof.h" - + unsigned long fs_buffer_size = 131072; unsigned long fs_cpu_buffer_size = 8192; unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */ @@ -117,11 +123,206 @@ static ssize_t dump_write(struct file * file, char const __user * buf, size_t co static struct file_operations dump_fops = { .write = dump_write, }; - + +#define TMPBUFSIZE 512 + +#ifdef CONFIG_XEN +static unsigned int adomains = 0; +static int active_domains[MAX_OPROF_DOMAINS + 1]; +static DEFINE_MUTEX(adom_mutex); + +static ssize_t adomain_write(struct file * file, char const __user * buf, + size_t count, loff_t * offset) +{ + char *tmpbuf; + char *startp, *endp; + int i; + unsigned long val; + ssize_t retval = count; + + if (*offset) + return -EINVAL; + if (count > TMPBUFSIZE - 1) + return -EINVAL; + + if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) + return -ENOMEM; + + if (copy_from_user(tmpbuf, buf, count)) { + kfree(tmpbuf); + return -EFAULT; + } + tmpbuf[count] = 0; + + mutex_lock(&adom_mutex); + + startp = tmpbuf; + /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */ + for (i = 0; i <= MAX_OPROF_DOMAINS; i++) { + val = simple_strtoul(startp, &endp, 0); + if (endp == startp) + break; + while (ispunct(*endp) || isspace(*endp)) + endp++; + active_domains[i] = val; + if (active_domains[i] != val) + /* Overflow, force error below */ + i = MAX_OPROF_DOMAINS + 1; + startp = endp; + } + /* Force error on trailing junk */ + adomains = *startp ? MAX_OPROF_DOMAINS + 1 : i; + + kfree(tmpbuf); + + if (adomains > MAX_OPROF_DOMAINS + || oprofile_set_active(active_domains, adomains)) { + adomains = 0; + retval = -EINVAL; + } + + mutex_unlock(&adom_mutex); + return retval; +} + +static ssize_t adomain_read(struct file * file, char __user * buf, + size_t count, loff_t * offset) +{ + char * tmpbuf; + size_t len; + int i; + ssize_t retval; + + if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) + return -ENOMEM; + + mutex_lock(&adom_mutex); + + len = 0; + for (i = 0; i < adomains; i++) + len += snprintf(tmpbuf + len, + len < TMPBUFSIZE ? TMPBUFSIZE - len : 0, + "%u ", active_domains[i]); + WARN_ON(len > TMPBUFSIZE); + if (len != 0 && len <= TMPBUFSIZE) + tmpbuf[len-1] = '\n'; + + mutex_unlock(&adom_mutex); + + retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len); + + kfree(tmpbuf); + return retval; +} + + +static struct file_operations active_domain_ops = { + .read = adomain_read, + .write = adomain_write, +}; + +static unsigned int pdomains = 0; +static int passive_domains[MAX_OPROF_DOMAINS]; +static DEFINE_MUTEX(pdom_mutex); + +static ssize_t pdomain_write(struct file * file, char const __user * buf, + size_t count, loff_t * offset) +{ + char *tmpbuf; + char *startp, *endp; + int i; + unsigned long val; + ssize_t retval = count; + + if (*offset) + return -EINVAL; + if (count > TMPBUFSIZE - 1) + return -EINVAL; + + if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) + return -ENOMEM; + + if (copy_from_user(tmpbuf, buf, count)) { + kfree(tmpbuf); + return -EFAULT; + } + tmpbuf[count] = 0; + + mutex_lock(&pdom_mutex); + + startp = tmpbuf; + /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */ + for (i = 0; i <= MAX_OPROF_DOMAINS; i++) { + val = simple_strtoul(startp, &endp, 0); + if (endp == startp) + break; + while (ispunct(*endp) || isspace(*endp)) + endp++; + passive_domains[i] = val; + if (passive_domains[i] != val) + /* Overflow, force error below */ + i = MAX_OPROF_DOMAINS + 1; + startp = endp; + } + /* Force error on trailing junk */ + pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i; + + kfree(tmpbuf); + + if (pdomains > MAX_OPROF_DOMAINS + || oprofile_set_passive(passive_domains, pdomains)) { + pdomains = 0; + retval = -EINVAL; + } + + mutex_unlock(&pdom_mutex); + return retval; +} + +static ssize_t pdomain_read(struct file * file, char __user * buf, + size_t count, loff_t * offset) +{ + char * tmpbuf; + size_t len; + int i; + ssize_t retval; + + if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) + return -ENOMEM; + + mutex_lock(&pdom_mutex); + + len = 0; + for (i = 0; i < pdomains; i++) + len += snprintf(tmpbuf + len, + len < TMPBUFSIZE ? TMPBUFSIZE - len : 0, + "%u ", passive_domains[i]); + WARN_ON(len > TMPBUFSIZE); + if (len != 0 && len <= TMPBUFSIZE) + tmpbuf[len-1] = '\n'; + + mutex_unlock(&pdom_mutex); + + retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len); + + kfree(tmpbuf); + return retval; +} + +static struct file_operations passive_domain_ops = { + .read = pdomain_read, + .write = pdomain_write, +}; +#endif /* CONFIG_XEN */ + void oprofile_create_files(struct super_block * sb, struct dentry * root) { oprofilefs_create_file(sb, root, "enable", &enable_fops); oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); +#ifdef CONFIG_XEN + oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops); + oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops); +#endif oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 4d762fc48..065ea43aa 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -5,6 +5,7 @@ config PCI_MSI bool "Message Signaled Interrupts (MSI and MSI-X)" depends on PCI depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 + depends on !XEN help This allows device drivers to enable MSI (Message Signaled Interrupts). Message Signaled Interrupts enable a device to diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d37847861..6e3786f4d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -427,6 +427,7 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev) pci_read_config_dword(dev, 0x48, ®ion); quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO"); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); /* @@ -1043,7 +1044,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asu DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc ); static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) { diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 6ded52716..688421de9 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -396,7 +396,8 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) /* check if the resource is already in use, skip if the * device is active because it itself may be in use */ if(!dev->active) { - if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL)) + if (request_irq(*irq, pnp_test_handler, + SA_INTERRUPT|SA_PROBEIRQ, "pnp", NULL)) return 0; free_irq(*irq, NULL); } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 0bab60a20..38aad8321 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -420,7 +420,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, } tcph = eddp->skb->h.th; while (eddp->skb_offset < eddp->skb->len) { - data_len = min((int)skb_shinfo(eddp->skb)->tso_size, + data_len = min((int)skb_shinfo(eddp->skb)->gso_size, (int)(eddp->skb->len - eddp->skb_offset)); /* prepare qdio hdr */ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){ @@ -515,20 +515,20 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, QETH_DBF_TEXT(trace, 5, "eddpcanp"); /* can we put multiple skbs in one page? */ - skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); + skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len); if (skbs_per_page > 1){ - ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) / + ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) / skbs_per_page + 1; ctx->elements_per_skb = 1; } else { /* no -> how many elements per skb? */ - ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len + + ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len + PAGE_SIZE) >> PAGE_SHIFT; ctx->num_pages = ctx->elements_per_skb * - (skb_shinfo(skb)->tso_segs + 1); + (skb_shinfo(skb)->gso_segs + 1); } ctx->num_elements = ctx->elements_per_skb * - (skb_shinfo(skb)->tso_segs + 1); + (skb_shinfo(skb)->gso_segs + 1); } static inline struct qeth_eddp_context * diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 9e671a48c..290866932 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -4417,7 +4417,6 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) struct qeth_eddp_context *ctx = NULL; int tx_bytes = skb->len; unsigned short nr_frags = skb_shinfo(skb)->nr_frags; - unsigned short tso_size = skb_shinfo(skb)->tso_size; int rc; QETH_DBF_TEXT(trace, 6, "sendpkt"); @@ -4453,7 +4452,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; - if (skb_shinfo(skb)->tso_size) + if (skb_is_gso(skb)) large_send = card->options.large_send; /*are we able to do TSO ? If so ,prepare and send it from here */ @@ -4500,9 +4499,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) card->stats.tx_packets++; card->stats.tx_bytes += tx_bytes; #ifdef CONFIG_QETH_PERF_STATS - if (tso_size && - !(large_send == QETH_LARGE_SEND_NO)) { - card->perf_stats.large_send_bytes += tx_bytes; + if (skb_is_gso(skb) && !(large_send == QETH_LARGE_SEND_NO)) { + card->perf_stats.large_send_bytes += skb->len; card->perf_stats.large_send_cnt++; } if (nr_frags > 0){ diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 24ef40ca9..593f29814 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) hdr->ext.hdr_version = 1; hdr->ext.hdr_len = 28; /*insert non-fix values */ - hdr->ext.mss = skb_shinfo(skb)->tso_size; + hdr->ext.mss = skb_shinfo(skb)->gso_size; hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - sizeof(struct qeth_hdr_tso)); diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index a262e384c..81803a16f 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -33,7 +33,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o -obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o +obj-$(CONFIG_ISCSI_TCP) += iscsi_tcp.o obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index b4743a9ec..2068b6682 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3,8 +3,7 @@ * * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman - * Copyright (C) 2005 - 2006 Mike Christie - * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2005 Mike Christie * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -37,28 +36,37 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include "iscsi_tcp.h" -#define ISCSI_TCP_VERSION "1.0-595" - MODULE_AUTHOR("Dmitry Yusupov , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); -MODULE_VERSION(ISCSI_TCP_VERSION); +MODULE_VERSION("0:4.445"); /* #define DEBUG_TCP */ +/* #define DEBUG_SCSI */ #define DEBUG_ASSERT #ifdef DEBUG_TCP -#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt) +#define debug_tcp(fmt...) printk(KERN_DEBUG "tcp: " fmt) #else #define debug_tcp(fmt...) #endif +#ifdef DEBUG_SCSI +#define debug_scsi(fmt...) printk(KERN_DEBUG "scsi: " fmt) +#else +#define debug_scsi(fmt...) +#endif + #ifndef DEBUG_ASSERT #ifdef BUG_ON #undef BUG_ON @@ -66,9 +74,22 @@ MODULE_VERSION(ISCSI_TCP_VERSION); #define BUG_ON(expr) #endif +#define INVALID_SN_DELTA 0xffff + static unsigned int iscsi_max_lun = 512; module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); +/* global data */ +static kmem_cache_t *taskcache; + +static inline void +iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) +{ + sg_init_one(&ibuf->sg, (u8 *)vbuf, size); + ibuf->sent = 0; + ibuf->use_sendmsg = 0; +} + static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { @@ -109,39 +130,68 @@ static inline void iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, u8* crc) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - - crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc); + crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc); buf->sg.length += sizeof(uint32_t); } +static void +iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) +{ + struct iscsi_session *session = conn->session; + unsigned long flags; + + spin_lock_irqsave(&session->lock, flags); + if (session->conn_cnt == 1 || session->leadconn == conn) + session->state = ISCSI_STATE_FAILED; + spin_unlock_irqrestore(&session->lock, flags); + set_bit(SUSPEND_BIT, &conn->suspend_tx); + set_bit(SUSPEND_BIT, &conn->suspend_rx); + iscsi_conn_error(conn->cls_conn, err); +} + static inline int -iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn) +iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) { - struct sk_buff *skb = tcp_conn->in.skb; + uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); + uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); + + if (max_cmdsn < exp_cmdsn -1 && + max_cmdsn > exp_cmdsn - INVALID_SN_DELTA) + return ISCSI_ERR_MAX_CMDSN; + if (max_cmdsn > session->max_cmdsn || + max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA) + session->max_cmdsn = max_cmdsn; + if (exp_cmdsn > session->exp_cmdsn || + exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA) + session->exp_cmdsn = exp_cmdsn; + + return 0; +} - tcp_conn->in.zero_copy_hdr = 0; +static inline int +iscsi_hdr_extract(struct iscsi_conn *conn) +{ + struct sk_buff *skb = conn->in.skb; - if (tcp_conn->in.copy >= tcp_conn->hdr_size && - tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) { + if (conn->in.copy >= conn->hdr_size && + conn->in_progress == IN_PROGRESS_WAIT_HEADER) { /* * Zero-copy PDU Header: using connection context * to store header pointer. */ if (skb_shinfo(skb)->frag_list == NULL && - !skb_shinfo(skb)->nr_frags) { - tcp_conn->in.hdr = (struct iscsi_hdr *) - ((char*)skb->data + tcp_conn->in.offset); - tcp_conn->in.zero_copy_hdr = 1; - } else { + !skb_shinfo(skb)->nr_frags) + conn->in.hdr = (struct iscsi_hdr *) + ((char*)skb->data + conn->in.offset); + else { /* ignoring return code since we checked * in.copy before */ - skb_copy_bits(skb, tcp_conn->in.offset, - &tcp_conn->hdr, tcp_conn->hdr_size); - tcp_conn->in.hdr = &tcp_conn->hdr; + skb_copy_bits(skb, conn->in.offset, + &conn->hdr, conn->hdr_size); + conn->in.hdr = &conn->hdr; } - tcp_conn->in.offset += tcp_conn->hdr_size; - tcp_conn->in.copy -= tcp_conn->hdr_size; + conn->in.offset += conn->hdr_size; + conn->in.copy -= conn->hdr_size; } else { int hdr_remains; int copylen; @@ -151,51 +201,118 @@ iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn) * copying it... This'll happen quite rarely. */ - if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) - tcp_conn->in.hdr_offset = 0; + if (conn->in_progress == IN_PROGRESS_WAIT_HEADER) + conn->in.hdr_offset = 0; - hdr_remains = tcp_conn->hdr_size - tcp_conn->in.hdr_offset; + hdr_remains = conn->hdr_size - conn->in.hdr_offset; BUG_ON(hdr_remains <= 0); - copylen = min(tcp_conn->in.copy, hdr_remains); - skb_copy_bits(skb, tcp_conn->in.offset, - (char*)&tcp_conn->hdr + tcp_conn->in.hdr_offset, - copylen); + copylen = min(conn->in.copy, hdr_remains); + skb_copy_bits(skb, conn->in.offset, + (char*)&conn->hdr + conn->in.hdr_offset, copylen); debug_tcp("PDU gather offset %d bytes %d in.offset %d " - "in.copy %d\n", tcp_conn->in.hdr_offset, copylen, - tcp_conn->in.offset, tcp_conn->in.copy); + "in.copy %d\n", conn->in.hdr_offset, copylen, + conn->in.offset, conn->in.copy); - tcp_conn->in.offset += copylen; - tcp_conn->in.copy -= copylen; + conn->in.offset += copylen; + conn->in.copy -= copylen; if (copylen < hdr_remains) { - tcp_conn->in_progress = IN_PROGRESS_HEADER_GATHER; - tcp_conn->in.hdr_offset += copylen; + conn->in_progress = IN_PROGRESS_HEADER_GATHER; + conn->in.hdr_offset += copylen; return -EAGAIN; } - tcp_conn->in.hdr = &tcp_conn->hdr; - tcp_conn->discontiguous_hdr_cnt++; - tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; + conn->in.hdr = &conn->hdr; + conn->discontiguous_hdr_cnt++; + conn->in_progress = IN_PROGRESS_WAIT_HEADER; } return 0; } -/* - * must be called with session lock - */ -static void -__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +static inline void +iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct scsi_cmnd *sc; + struct scsi_cmnd *sc = ctask->sc; + struct iscsi_session *session = conn->session; - sc = ctask->sc; - if (unlikely(!sc)) + spin_lock(&session->lock); + if (unlikely(!sc)) { + spin_unlock(&session->lock); return; + } + if (sc->sc_data_direction == DMA_TO_DEVICE) { + struct iscsi_data_task *dtask, *n; + /* WRITE: cleanup Data-Out's if any */ + list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { + list_del(&dtask->item); + mempool_free(dtask, ctask->datapool); + } + } + ctask->xmstate = XMSTATE_IDLE; + ctask->r2t = NULL; + ctask->sc = NULL; + __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + spin_unlock(&session->lock); +} + +/** + * iscsi_cmd_rsp - SCSI Command Response processing + * @conn: iscsi connection + * @ctask: scsi command task + **/ +static int +iscsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +{ + int rc; + struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)conn->in.hdr; + struct iscsi_session *session = conn->session; + struct scsi_cmnd *sc = ctask->sc; + + rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); + if (rc) { + sc->result = (DID_ERROR << 16); + goto out; + } + + conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; + + sc->result = (DID_OK << 16) | rhdr->cmd_status; + + if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { + sc->result = (DID_ERROR << 16); + goto out; + } + + if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION && conn->senselen) { + int sensecopy = min(conn->senselen, SCSI_SENSE_BUFFERSIZE); - tcp_ctask->xmstate = XMSTATE_IDLE; - tcp_ctask->r2t = NULL; + memcpy(sc->sense_buffer, conn->data + 2, sensecopy); + debug_scsi("copied %d bytes of sense\n", sensecopy); + } + + if (sc->sc_data_direction == DMA_TO_DEVICE) + goto out; + + if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { + int res_count = be32_to_cpu(rhdr->residual_count); + + if (res_count > 0 && res_count <= sc->request_bufflen) + sc->resid = res_count; + else + sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; + } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) + sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; + else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) + sc->resid = be32_to_cpu(rhdr->residual_count); + +out: + debug_scsi("done [sc %lx res %d itt 0x%x]\n", + (long)sc, sc->result, ctask->itt); + conn->scsirsp_pdus_cnt++; + iscsi_ctask_cleanup(conn, ctask); + sc->scsi_done(sc); + return rc; } /** @@ -207,9 +324,7 @@ static int iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { int rc; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr; + struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)conn->in.hdr; struct iscsi_session *session = conn->session; int datasn = be32_to_cpu(rhdr->datasn); @@ -219,9 +334,9 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) /* * setup Data-In byte counter (gets decremented..) */ - ctask->data_count = tcp_conn->in.datalen; + ctask->data_count = conn->in.datalen; - if (tcp_conn->in.datalen == 0) + if (conn->in.datalen == 0) return 0; if (ctask->datasn != datasn) @@ -229,8 +344,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->datasn++; - tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); - if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length) + ctask->data_offset = be32_to_cpu(rhdr->offset); + if (ctask->data_offset + conn->in.datalen > ctask->total_length) return ISCSI_ERR_DATA_OFFSET; if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) { @@ -275,17 +390,19 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_r2t_info *r2t) { struct iscsi_data *hdr; + struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - hdr = &r2t->dtask.hdr; + dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); + BUG_ON(!dtask); + hdr = &dtask->hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->solicit_datasn); r2t->solicit_datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr->itt; + memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr.itt; hdr->exp_statsn = r2t->exp_statsn; hdr->offset = cpu_to_be32(r2t->data_offset); if (r2t->data_length > conn->max_xmit_dlength) { @@ -301,9 +418,11 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, r2t->sent = 0; - iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, + iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); + r2t->dtask = dtask; + if (sc->use_sg) { int i, sg_count = 0; struct scatterlist *sg = sc->request_buffer; @@ -332,9 +451,11 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, } BUG_ON(r2t->sg == NULL); } else - iscsi_buf_init_iov(&tcp_ctask->sendbuf, + iscsi_buf_init_iov(&ctask->sendbuf, (char*)sc->request_buffer + r2t->data_offset, r2t->data_count); + + list_add(&dtask->item, &ctask->dataqueue); } /** @@ -347,16 +468,17 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_r2t_info *r2t; struct iscsi_session *session = conn->session; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; + struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)conn->in.hdr; int r2tsn = be32_to_cpu(rhdr->r2tsn); int rc; - if (tcp_conn->in.datalen) + if (conn->in.ahslen) + return ISCSI_ERR_AHSLEN; + + if (conn->in.datalen) return ISCSI_ERR_DATALEN; - if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) + if (ctask->exp_r2tsn && ctask->exp_r2tsn != r2tsn) return ISCSI_ERR_R2TSN; rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); @@ -374,7 +496,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) spin_unlock(&session->lock); return 0; } - rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = __kfifo_get(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); BUG_ON(!rc); r2t->exp_statsn = rhdr->statsn; @@ -396,10 +518,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_solicit_data_init(conn, ctask, r2t); - tcp_ctask->exp_r2tsn = r2tsn + 1; - tcp_ctask->xmstate |= XMSTATE_SOL_HDR; - __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); + ctask->exp_r2tsn = r2tsn + 1; + ctask->xmstate |= XMSTATE_SOL_HDR; + __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); + __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); scsi_queue_work(session->host, &conn->xmitwork); conn->r2t_pdus_cnt++; @@ -409,136 +531,258 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } static int -iscsi_tcp_hdr_recv(struct iscsi_conn *conn) +iscsi_hdr_recv(struct iscsi_conn *conn) { - int rc = 0, opcode, ahslen; + int rc = 0; struct iscsi_hdr *hdr; + struct iscsi_cmd_task *ctask; struct iscsi_session *session = conn->session; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - uint32_t cdgst, rdgst = 0, itt; + uint32_t cdgst, rdgst = 0; - hdr = tcp_conn->in.hdr; + hdr = conn->in.hdr; /* verify PDU length */ - tcp_conn->in.datalen = ntoh24(hdr->dlength); - if (tcp_conn->in.datalen > conn->max_recv_dlength) { + conn->in.datalen = ntoh24(hdr->dlength); + if (conn->in.datalen > conn->max_recv_dlength) { printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n", - tcp_conn->in.datalen, conn->max_recv_dlength); + conn->in.datalen, conn->max_recv_dlength); return ISCSI_ERR_DATALEN; } - tcp_conn->data_copied = 0; + conn->data_copied = 0; /* read AHS */ - ahslen = hdr->hlength << 2; - tcp_conn->in.offset += ahslen; - tcp_conn->in.copy -= ahslen; - if (tcp_conn->in.copy < 0) { + conn->in.ahslen = hdr->hlength * 4; + conn->in.offset += conn->in.ahslen; + conn->in.copy -= conn->in.ahslen; + if (conn->in.copy < 0) { printk(KERN_ERR "iscsi_tcp: can't handle AHS with length " - "%d bytes\n", ahslen); + "%d bytes\n", conn->in.ahslen); return ISCSI_ERR_AHSLEN; } /* calculate read padding */ - tcp_conn->in.padding = tcp_conn->in.datalen & (ISCSI_PAD_LEN-1); - if (tcp_conn->in.padding) { - tcp_conn->in.padding = ISCSI_PAD_LEN - tcp_conn->in.padding; - debug_scsi("read padding %d bytes\n", tcp_conn->in.padding); + conn->in.padding = conn->in.datalen & (ISCSI_PAD_LEN-1); + if (conn->in.padding) { + conn->in.padding = ISCSI_PAD_LEN - conn->in.padding; + debug_scsi("read padding %d bytes\n", conn->in.padding); } if (conn->hdrdgst_en) { struct scatterlist sg; sg_init_one(&sg, (u8 *)hdr, - sizeof(struct iscsi_hdr) + ahslen); - crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst); + sizeof(struct iscsi_hdr) + conn->in.ahslen); + crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst); rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + - ahslen); + conn->in.ahslen); if (cdgst != rdgst) { - printk(KERN_ERR "iscsi_tcp: hdrdgst error " - "recv 0x%x calc 0x%x\n", rdgst, cdgst); + printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error " + "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst, + cdgst); return ISCSI_ERR_HDR_DGST; } } - opcode = hdr->opcode & ISCSI_OPCODE_MASK; + /* save opcode for later */ + conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK; + /* verify itt (itt encoding: age+cid+itt) */ - rc = iscsi_verify_itt(conn, hdr, &itt); - if (rc == ISCSI_ERR_NO_SCSI_CMD) { - tcp_conn->in.datalen = 0; /* force drop */ - return 0; - } else if (rc) - return rc; + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + if ((hdr->itt & AGE_MASK) != + (session->age << AGE_SHIFT)) { + printk(KERN_ERR "iscsi_tcp: received itt %x expected " + "session age (%x)\n", hdr->itt, + session->age & AGE_MASK); + return ISCSI_ERR_BAD_ITT; + } + + if ((hdr->itt & CID_MASK) != (conn->id << CID_SHIFT)) { + printk(KERN_ERR "iscsi_tcp: received itt %x, expected " + "CID (%x)\n", hdr->itt, conn->id); + return ISCSI_ERR_BAD_ITT; + } + conn->in.itt = hdr->itt & ITT_MASK; + } else + conn->in.itt = hdr->itt; debug_tcp("opcode 0x%x offset %d copy %d ahslen %d datalen %d\n", - opcode, tcp_conn->in.offset, tcp_conn->in.copy, - ahslen, tcp_conn->in.datalen); + hdr->opcode, conn->in.offset, conn->in.copy, + conn->in.ahslen, conn->in.datalen); - switch(opcode) { - case ISCSI_OP_SCSI_DATA_IN: - tcp_conn->in.ctask = session->cmds[itt]; - rc = iscsi_data_rsp(conn, tcp_conn->in.ctask); - /* fall through */ - case ISCSI_OP_SCSI_CMD_RSP: - tcp_conn->in.ctask = session->cmds[itt]; - if (tcp_conn->in.datalen) - goto copy_hdr; - - spin_lock(&session->lock); - __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); - rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); - spin_unlock(&session->lock); - break; - case ISCSI_OP_R2T: - tcp_conn->in.ctask = session->cmds[itt]; - if (ahslen) - rc = ISCSI_ERR_AHSLEN; - else if (tcp_conn->in.ctask->sc->sc_data_direction == - DMA_TO_DEVICE) - rc = iscsi_r2t_rsp(conn, tcp_conn->in.ctask); - else - rc = ISCSI_ERR_PROTO; - break; - case ISCSI_OP_LOGIN_RSP: - case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_LOGOUT_RSP: - case ISCSI_OP_NOOP_IN: - case ISCSI_OP_REJECT: - case ISCSI_OP_ASYNC_EVENT: - if (tcp_conn->in.datalen) - goto copy_hdr; - /* fall through */ - case ISCSI_OP_SCSI_TMFUNC_RSP: - rc = iscsi_complete_pdu(conn, hdr, NULL, 0); - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } + if (conn->in.itt < session->cmds_max) { + ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt]; - return rc; + if (!ctask->sc) { + printk(KERN_INFO "iscsi_tcp: dropping ctask with " + "itt 0x%x\n", ctask->itt); + conn->in.datalen = 0; /* force drop */ + return 0; + } -copy_hdr: - /* - * if we did zero copy for the header but we will need multiple - * skbs to complete the command then we have to copy the header - * for later use - */ - if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy < - (tcp_conn->in.datalen + tcp_conn->in.padding + - (conn->datadgst_en ? 4 : 0))) { - debug_tcp("Copying header for later use. in.copy %d in.datalen" - " %d\n", tcp_conn->in.copy, tcp_conn->in.datalen); - memcpy(&tcp_conn->hdr, tcp_conn->in.hdr, - sizeof(struct iscsi_hdr)); - tcp_conn->in.hdr = &tcp_conn->hdr; - tcp_conn->in.zero_copy_hdr = 0; - } - return 0; + if (ctask->sc->SCp.phase != session->age) { + printk(KERN_ERR "iscsi_tcp: ctask's session age %d, " + "expected %d\n", ctask->sc->SCp.phase, + session->age); + return ISCSI_ERR_SESSION_FAILED; + } + + conn->in.ctask = ctask; + + debug_scsi("rsp [op 0x%x cid %d sc %lx itt 0x%x len %d]\n", + hdr->opcode, conn->id, (long)ctask->sc, + ctask->itt, conn->in.datalen); + + switch(conn->in.opcode) { + case ISCSI_OP_SCSI_CMD_RSP: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + if (!conn->in.datalen) + rc = iscsi_cmd_rsp(conn, ctask); + else + /* + * got sense or response data; copying PDU + * Header to the connection's header + * placeholder + */ + memcpy(&conn->hdr, hdr, + sizeof(struct iscsi_hdr)); + break; + case ISCSI_OP_SCSI_DATA_IN: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + /* save flags for non-exceptional status */ + conn->in.flags = hdr->flags; + /* save cmd_status for sense data */ + conn->in.cmd_status = + ((struct iscsi_data_rsp*)hdr)->cmd_status; + rc = iscsi_data_rsp(conn, ctask); + break; + case ISCSI_OP_R2T: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) + rc = iscsi_r2t_rsp(conn, ctask); + else + rc = ISCSI_ERR_PROTO; + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else if (conn->in.itt >= ISCSI_MGMT_ITT_OFFSET && + conn->in.itt < ISCSI_MGMT_ITT_OFFSET + + session->mgmtpool_max) { + struct iscsi_mgmt_task *mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[conn->in.itt - + ISCSI_MGMT_ITT_OFFSET]; + + debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", + conn->in.opcode, conn->id, mtask->itt, + conn->in.datalen); + + switch(conn->in.opcode) { + case ISCSI_OP_LOGIN_RSP: + case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_LOGOUT_RSP: + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + break; + + if (!conn->in.datalen) { + rc = iscsi_recv_pdu(conn->cls_conn, hdr, + NULL, 0); + if (conn->login_mtask != mtask) { + spin_lock(&session->lock); + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + spin_unlock(&session->lock); + } + } + break; + case ISCSI_OP_SCSI_TMFUNC_RSP: + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + break; + + if (conn->in.datalen || conn->in.ahslen) { + rc = ISCSI_ERR_PROTO; + break; + } + conn->tmfrsp_pdus_cnt++; + spin_lock(&session->lock); + if (conn->tmabort_state == TMABORT_INITIAL) { + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + conn->tmabort_state = + ((struct iscsi_tm_rsp *)hdr)-> + response == ISCSI_TMF_RSP_COMPLETE ? + TMABORT_SUCCESS:TMABORT_FAILED; + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } + spin_unlock(&session->lock); + break; + case ISCSI_OP_NOOP_IN: + if (hdr->ttt != ISCSI_RESERVED_TAG) { + rc = ISCSI_ERR_PROTO; + break; + } + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + break; + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + + if (!conn->in.datalen) { + struct iscsi_mgmt_task *mtask; + + rc = iscsi_recv_pdu(conn->cls_conn, hdr, + NULL, 0); + mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[conn->in.itt - + ISCSI_MGMT_ITT_OFFSET]; + if (conn->login_mtask != mtask) { + spin_lock(&session->lock); + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + spin_unlock(&session->lock); + } + } + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else if (conn->in.itt == ISCSI_RESERVED_TAG) { + switch(conn->in.opcode) { + case ISCSI_OP_NOOP_IN: + if (!conn->in.datalen) { + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) + rc = iscsi_recv_pdu(conn->cls_conn, + hdr, NULL, 0); + } else + rc = ISCSI_ERR_PROTO; + break; + case ISCSI_OP_REJECT: + /* we need sth like iscsi_reject_rsp()*/ + case ISCSI_OP_ASYNC_EVENT: + /* we need sth like iscsi_async_event_rsp() */ + rc = ISCSI_ERR_BAD_OPCODE; + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else + rc = ISCSI_ERR_BAD_ITT; + + return rc; } /** * iscsi_ctask_copy - copy skb bits to the destanation cmd task - * @conn: iscsi tcp connection + * @conn: iscsi connection * @ctask: scsi command task * @buf: buffer to copy to * @buf_size: size of buffer @@ -560,113 +804,110 @@ copy_hdr: * buf_left left to copy from in progress buffer **/ static inline int -iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, +iscsi_ctask_copy(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, void *buf, int buf_size, int offset) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - int buf_left = buf_size - (tcp_conn->data_copied + offset); - int size = min(tcp_conn->in.copy, buf_left); + int buf_left = buf_size - (conn->data_copied + offset); + int size = min(conn->in.copy, buf_left); int rc; size = min(size, ctask->data_count); debug_tcp("ctask_copy %d bytes at offset %d copied %d\n", - size, tcp_conn->in.offset, tcp_conn->in.copied); + size, conn->in.offset, conn->in.copied); BUG_ON(size <= 0); - BUG_ON(tcp_ctask->sent + size > ctask->total_length); + BUG_ON(ctask->sent + size > ctask->total_length); - rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, - (char*)buf + (offset + tcp_conn->data_copied), size); + rc = skb_copy_bits(conn->in.skb, conn->in.offset, + (char*)buf + (offset + conn->data_copied), size); /* must fit into skb->len */ BUG_ON(rc); - tcp_conn->in.offset += size; - tcp_conn->in.copy -= size; - tcp_conn->in.copied += size; - tcp_conn->data_copied += size; - tcp_ctask->sent += size; + conn->in.offset += size; + conn->in.copy -= size; + conn->in.copied += size; + conn->data_copied += size; + ctask->sent += size; ctask->data_count -= size; - BUG_ON(tcp_conn->in.copy < 0); + BUG_ON(conn->in.copy < 0); BUG_ON(ctask->data_count < 0); - if (buf_size != (tcp_conn->data_copied + offset)) { + if (buf_size != (conn->data_copied + offset)) { if (!ctask->data_count) { - BUG_ON(buf_size - tcp_conn->data_copied < 0); + BUG_ON(buf_size - conn->data_copied < 0); /* done with this PDU */ - return buf_size - tcp_conn->data_copied; + return buf_size - conn->data_copied; } return -EAGAIN; } /* done with this buffer or with both - PDU and buffer */ - tcp_conn->data_copied = 0; + conn->data_copied = 0; return 0; } /** * iscsi_tcp_copy - copy skb bits to the destanation buffer - * @conn: iscsi tcp connection + * @conn: iscsi connection + * @buf: buffer to copy to + * @buf_size: number of bytes to copy * * Notes: * The function calls skb_copy_bits() and updates per-connection * byte counters. **/ static inline int -iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) +iscsi_tcp_copy(struct iscsi_conn *conn, void *buf, int buf_size) { - void *buf = tcp_conn->data; - int buf_size = tcp_conn->in.datalen; - int buf_left = buf_size - tcp_conn->data_copied; - int size = min(tcp_conn->in.copy, buf_left); + int buf_left = buf_size - conn->data_copied; + int size = min(conn->in.copy, buf_left); int rc; debug_tcp("tcp_copy %d bytes at offset %d copied %d\n", - size, tcp_conn->in.offset, tcp_conn->data_copied); + size, conn->in.offset, conn->data_copied); BUG_ON(size <= 0); - rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, - (char*)buf + tcp_conn->data_copied, size); + rc = skb_copy_bits(conn->in.skb, conn->in.offset, + (char*)buf + conn->data_copied, size); BUG_ON(rc); - tcp_conn->in.offset += size; - tcp_conn->in.copy -= size; - tcp_conn->in.copied += size; - tcp_conn->data_copied += size; + conn->in.offset += size; + conn->in.copy -= size; + conn->in.copied += size; + conn->data_copied += size; - if (buf_size != tcp_conn->data_copied) + if (buf_size != conn->data_copied) return -EAGAIN; return 0; } static inline void -partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, - struct scatterlist *sg, int offset, int length) +partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg, + int offset, int length) { struct scatterlist temp; memcpy(&temp, sg, sizeof(struct scatterlist)); temp.offset = offset; temp.length = length; - crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1); + crypto_digest_update(conn->data_rx_tfm, &temp, 1); } static void -iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len) +iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len) { struct scatterlist tmp; sg_init_one(&tmp, buf, len); - crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1); + crypto_digest_update(conn->data_rx_tfm, &tmp, 1); } static int iscsi_scsi_data_in(struct iscsi_conn *conn) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct iscsi_cmd_task *ctask = tcp_conn->in.ctask; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_cmd_task *ctask = conn->in.ctask; struct scsi_cmnd *sc = ctask->sc; struct scatterlist *sg; int i, offset, rc = 0; @@ -678,33 +919,31 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) */ if (!sc->use_sg) { i = ctask->data_count; - rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer, - sc->request_bufflen, - tcp_ctask->data_offset); + rc = iscsi_ctask_copy(conn, ctask, sc->request_buffer, + sc->request_bufflen, ctask->data_offset); if (rc == -EAGAIN) return rc; if (conn->datadgst_en) - iscsi_recv_digest_update(tcp_conn, sc->request_buffer, - i); + iscsi_recv_digest_update(conn, sc->request_buffer, i); rc = 0; goto done; } - offset = tcp_ctask->data_offset; + offset = ctask->data_offset; sg = sc->request_buffer; - if (tcp_ctask->data_offset) - for (i = 0; i < tcp_ctask->sg_count; i++) + if (ctask->data_offset) + for (i = 0; i < ctask->sg_count; i++) offset -= sg[i].length; /* we've passed through partial sg*/ if (offset < 0) offset = 0; - for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) { + for (i = ctask->sg_count; i < sc->use_sg; i++) { char *dest; dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0); - rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset, + rc = iscsi_ctask_copy(conn, ctask, dest + sg[i].offset, sg[i].length, offset); kunmap_atomic(dest, KM_SOFTIRQ0); if (rc == -EAGAIN) @@ -713,17 +952,15 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) if (!rc) { if (conn->datadgst_en) { if (!offset) - crypto_digest_update( - tcp_conn->data_rx_tfm, - &sg[i], 1); + crypto_digest_update(conn->data_rx_tfm, + &sg[i], 1); else - partial_sg_digest_update(tcp_conn, - &sg[i], + partial_sg_digest_update(conn, &sg[i], sg[i].offset + offset, sg[i].length - offset); } offset = 0; - tcp_ctask->sg_count++; + ctask->sg_count++; } if (!ctask->data_count) { @@ -731,26 +968,25 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) /* * data-in is complete, but buffer not... */ - partial_sg_digest_update(tcp_conn, &sg[i], + partial_sg_digest_update(conn, &sg[i], sg[i].offset, sg[i].length-rc); rc = 0; break; } - if (!tcp_conn->in.copy) + if (!conn->in.copy) return -EAGAIN; } BUG_ON(ctask->data_count); done: /* check for non-exceptional status */ - if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { + if (conn->in.flags & ISCSI_FLAG_DATA_STATUS) { debug_scsi("done [sc %lx res %d itt 0x%x]\n", (long)sc, sc->result, ctask->itt); - spin_lock(&conn->session->lock); - __iscsi_ctask_cleanup(conn, ctask); - __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); - spin_unlock(&conn->session->lock); + conn->scsirsp_pdus_cnt++; + iscsi_ctask_cleanup(conn, ctask); + sc->scsi_done(sc); } return rc; @@ -759,38 +995,71 @@ done: static int iscsi_data_recv(struct iscsi_conn *conn) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - int rc = 0, opcode; + struct iscsi_session *session = conn->session; + int rc = 0; - opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK; - switch (opcode) { + switch(conn->in.opcode) { case ISCSI_OP_SCSI_DATA_IN: rc = iscsi_scsi_data_in(conn); break; - case ISCSI_OP_SCSI_CMD_RSP: - spin_lock(&conn->session->lock); - __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); - spin_unlock(&conn->session->lock); + case ISCSI_OP_SCSI_CMD_RSP: { + /* + * SCSI Sense Data: + * copying the entire Data Segment. + */ + if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) { + rc = -EAGAIN; + goto exit; + } + + /* + * check for sense + */ + conn->in.hdr = &conn->hdr; + conn->senselen = (conn->data[0] << 8) | conn->data[1]; + rc = iscsi_cmd_rsp(conn, conn->in.ctask); + if (!rc && conn->datadgst_en) + iscsi_recv_digest_update(conn, conn->data, + conn->in.datalen); + } + break; case ISCSI_OP_TEXT_RSP: case ISCSI_OP_LOGIN_RSP: - case ISCSI_OP_NOOP_IN: - case ISCSI_OP_ASYNC_EVENT: - case ISCSI_OP_REJECT: + case ISCSI_OP_NOOP_IN: { + struct iscsi_mgmt_task *mtask = NULL; + + if (conn->in.itt != ISCSI_RESERVED_TAG) + mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[conn->in.itt - + ISCSI_MGMT_ITT_OFFSET]; + /* * Collect data segment to the connection's data * placeholder */ - if (iscsi_tcp_copy(tcp_conn)) { + if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) { rc = -EAGAIN; goto exit; } - rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data, - tcp_conn->in.datalen); - if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) - iscsi_recv_digest_update(tcp_conn, tcp_conn->data, - tcp_conn->in.datalen); - break; + rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr, + conn->data, conn->in.datalen); + + if (!rc && conn->datadgst_en && + conn->in.opcode != ISCSI_OP_LOGIN_RSP) + iscsi_recv_digest_update(conn, conn->data, + conn->in.datalen); + + if (mtask && conn->login_mtask != mtask) { + spin_lock(&session->lock); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + spin_unlock(&session->lock); + } + } + break; + case ISCSI_OP_ASYNC_EVENT: + case ISCSI_OP_REJECT: default: BUG_ON(1); } @@ -811,7 +1080,6 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, { int rc; struct iscsi_conn *conn = rd_desc->arg.data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int processed; char pad[ISCSI_PAD_LEN]; struct scatterlist sg; @@ -820,15 +1088,15 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, * Save current SKB and its offset in the corresponding * connection context. */ - tcp_conn->in.copy = skb->len - offset; - tcp_conn->in.offset = offset; - tcp_conn->in.skb = skb; - tcp_conn->in.len = tcp_conn->in.copy; - BUG_ON(tcp_conn->in.copy <= 0); - debug_tcp("in %d bytes\n", tcp_conn->in.copy); + conn->in.copy = skb->len - offset; + conn->in.offset = offset; + conn->in.skb = skb; + conn->in.len = conn->in.copy; + BUG_ON(conn->in.copy <= 0); + debug_tcp("in %d bytes\n", conn->in.copy); more: - tcp_conn->in.copied = 0; + conn->in.copied = 0; rc = 0; if (unlikely(conn->suspend_rx)) { @@ -836,9 +1104,9 @@ more: return 0; } - if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER || - tcp_conn->in_progress == IN_PROGRESS_HEADER_GATHER) { - rc = iscsi_hdr_extract(tcp_conn); + if (conn->in_progress == IN_PROGRESS_WAIT_HEADER || + conn->in_progress == IN_PROGRESS_HEADER_GATHER) { + rc = iscsi_hdr_extract(conn); if (rc) { if (rc == -EAGAIN) goto nomore; @@ -851,91 +1119,90 @@ more: /* * Verify and process incoming PDU header. */ - rc = iscsi_tcp_hdr_recv(conn); - if (!rc && tcp_conn->in.datalen) { + rc = iscsi_hdr_recv(conn); + if (!rc && conn->in.datalen) { if (conn->datadgst_en) { - BUG_ON(!tcp_conn->data_rx_tfm); - crypto_digest_init(tcp_conn->data_rx_tfm); + BUG_ON(!conn->data_rx_tfm); + crypto_digest_init(conn->data_rx_tfm); } - tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; + conn->in_progress = IN_PROGRESS_DATA_RECV; } else if (rc) { iscsi_conn_failure(conn, rc); return 0; } } - if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { + if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { uint32_t recv_digest; - debug_tcp("extra data_recv offset %d copy %d\n", - tcp_conn->in.offset, tcp_conn->in.copy); - skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, + conn->in.offset, conn->in.copy); + skb_copy_bits(conn->in.skb, conn->in.offset, &recv_digest, 4); - tcp_conn->in.offset += 4; - tcp_conn->in.copy -= 4; - if (recv_digest != tcp_conn->in.datadgst) { + conn->in.offset += 4; + conn->in.copy -= 4; + if (recv_digest != conn->in.datadgst) { debug_tcp("iscsi_tcp: data digest error!" "0x%x != 0x%x\n", recv_digest, - tcp_conn->in.datadgst); + conn->in.datadgst); iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); return 0; } else { debug_tcp("iscsi_tcp: data digest match!" "0x%x == 0x%x\n", recv_digest, - tcp_conn->in.datadgst); - tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; + conn->in.datadgst); + conn->in_progress = IN_PROGRESS_WAIT_HEADER; } } - if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV && - tcp_conn->in.copy) { + if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) { debug_tcp("data_recv offset %d copy %d\n", - tcp_conn->in.offset, tcp_conn->in.copy); + conn->in.offset, conn->in.copy); rc = iscsi_data_recv(conn); if (rc) { - if (rc == -EAGAIN) + if (rc == -EAGAIN) { + rd_desc->count = conn->in.datalen - + conn->in.ctask->data_count; goto again; + } iscsi_conn_failure(conn, rc); return 0; } - tcp_conn->in.copy -= tcp_conn->in.padding; - tcp_conn->in.offset += tcp_conn->in.padding; + conn->in.copy -= conn->in.padding; + conn->in.offset += conn->in.padding; if (conn->datadgst_en) { - if (tcp_conn->in.padding) { - debug_tcp("padding -> %d\n", - tcp_conn->in.padding); - memset(pad, 0, tcp_conn->in.padding); - sg_init_one(&sg, pad, tcp_conn->in.padding); - crypto_digest_update(tcp_conn->data_rx_tfm, - &sg, 1); + if (conn->in.padding) { + debug_tcp("padding -> %d\n", conn->in.padding); + memset(pad, 0, conn->in.padding); + sg_init_one(&sg, pad, conn->in.padding); + crypto_digest_update(conn->data_rx_tfm, &sg, 1); } - crypto_digest_final(tcp_conn->data_rx_tfm, - (u8 *) & tcp_conn->in.datadgst); - debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); - tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; + crypto_digest_final(conn->data_rx_tfm, + (u8 *) & conn->in.datadgst); + debug_tcp("rx digest 0x%x\n", conn->in.datadgst); + conn->in_progress = IN_PROGRESS_DDIGEST_RECV; } else - tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; + conn->in_progress = IN_PROGRESS_WAIT_HEADER; } debug_tcp("f, processed %d from out of %d padding %d\n", - tcp_conn->in.offset - offset, (int)len, tcp_conn->in.padding); - BUG_ON(tcp_conn->in.offset - offset > len); + conn->in.offset - offset, (int)len, conn->in.padding); + BUG_ON(conn->in.offset - offset > len); - if (tcp_conn->in.offset - offset != len) { + if (conn->in.offset - offset != len) { debug_tcp("continue to process %d bytes\n", - (int)len - (tcp_conn->in.offset - offset)); + (int)len - (conn->in.offset - offset)); goto more; } nomore: - processed = tcp_conn->in.offset - offset; + processed = conn->in.offset - offset; BUG_ON(processed == 0); return processed; again: - processed = tcp_conn->in.offset - offset; + processed = conn->in.offset - offset; debug_tcp("c, processed %d from out of %d rd_desc_cnt %d\n", processed, (int)len, (int)rd_desc->count); BUG_ON(processed == 0); @@ -953,14 +1220,9 @@ iscsi_tcp_data_ready(struct sock *sk, int flag) read_lock(&sk->sk_callback_lock); - /* - * Use rd_desc to pass 'conn' to iscsi_tcp_data_recv. - * We set count to 1 because we want the network layer to - * hand us all the skbs that are available. iscsi_tcp_data_recv - * handled pdus that cross buffers or pdus that still need data. - */ + /* use rd_desc to pass 'conn' to iscsi_tcp_data_recv */ rd_desc.arg.data = conn; - rd_desc.count = 1; + rd_desc.count = 0; tcp_read_sock(sk, &rd_desc, iscsi_tcp_data_recv); read_unlock(&sk->sk_callback_lock); @@ -969,7 +1231,6 @@ iscsi_tcp_data_ready(struct sock *sk, int flag) static void iscsi_tcp_state_change(struct sock *sk) { - struct iscsi_tcp_conn *tcp_conn; struct iscsi_conn *conn; struct iscsi_session *session; void (*old_state_change)(struct sock *); @@ -986,8 +1247,7 @@ iscsi_tcp_state_change(struct sock *sk) iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); } - tcp_conn = conn->dd_data; - old_state_change = tcp_conn->old_state_change; + old_state_change = conn->old_state_change; read_unlock(&sk->sk_callback_lock); @@ -1002,25 +1262,23 @@ static void iscsi_write_space(struct sock *sk) { struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - - tcp_conn->old_write_space(sk); + conn->old_write_space(sk); debug_tcp("iscsi_write_space: cid %d\n", conn->id); + clear_bit(SUSPEND_BIT, &conn->suspend_tx); scsi_queue_work(conn->session->host, &conn->xmitwork); } static void iscsi_conn_set_callbacks(struct iscsi_conn *conn) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct sock *sk = tcp_conn->sock->sk; + struct sock *sk = conn->sock->sk; /* assign new callbacks */ write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = conn; - tcp_conn->old_data_ready = sk->sk_data_ready; - tcp_conn->old_state_change = sk->sk_state_change; - tcp_conn->old_write_space = sk->sk_write_space; + conn->old_data_ready = sk->sk_data_ready; + conn->old_state_change = sk->sk_state_change; + conn->old_write_space = sk->sk_write_space; sk->sk_data_ready = iscsi_tcp_data_ready; sk->sk_state_change = iscsi_tcp_state_change; sk->sk_write_space = iscsi_write_space; @@ -1030,15 +1288,14 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn) static void iscsi_conn_restore_callbacks(struct iscsi_conn *conn) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct sock *sk = tcp_conn->sock->sk; + struct sock *sk = conn->sock->sk; /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = NULL; - sk->sk_data_ready = tcp_conn->old_data_ready; - sk->sk_state_change = tcp_conn->old_state_change; - sk->sk_write_space = tcp_conn->old_write_space; + sk->sk_data_ready = conn->old_data_ready; + sk->sk_state_change = conn->old_state_change; + sk->sk_write_space = conn->old_write_space; sk->sk_no_check = 0; write_unlock_bh(&sk->sk_callback_lock); } @@ -1053,9 +1310,8 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) static inline int iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct socket *sk = tcp_conn->sock; - int offset = buf->sg.offset + buf->sent, res; + struct socket *sk = conn->sock; + int offset = buf->sg.offset + buf->sent; /* * if we got use_sg=0 or are sending something we kmallocd @@ -1066,22 +1322,9 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) * slab case. */ if (buf->use_sendmsg) - res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags); - else - res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags); - - if (res >= 0) { - conn->txdata_octets += res; - buf->sent += res; - return res; - } - - tcp_conn->sendpage_failures_cnt++; - if (res == -EAGAIN) - res = -ENOBUFS; + return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); else - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - return res; + return conn->sendpage(sk, buf->sg.page, offset, size, flags); } /** @@ -1107,10 +1350,16 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) res = iscsi_send(conn, buf, size, flags); debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); if (res >= 0) { + conn->txdata_octets += res; + buf->sent += res; if (size != res) return -EAGAIN; return 0; - } + } else if (res == -EAGAIN) { + conn->sendpage_failures_cnt++; + set_bit(SUSPEND_BIT, &conn->suspend_tx); + } else if (res == -EPIPE) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); return res; } @@ -1143,46 +1392,47 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", size, buf->sent, *count, *sent, res); if (res >= 0) { + conn->txdata_octets += res; + buf->sent += res; *count -= res; *sent += res; if (size != res) return -EAGAIN; return 0; - } + } else if (res == -EAGAIN) { + conn->sendpage_failures_cnt++; + set_bit(SUSPEND_BIT, &conn->suspend_tx); + } else if (res == -EPIPE) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); return res; } static inline void -iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, - struct iscsi_cmd_task *ctask) +iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - - BUG_ON(!tcp_conn->data_tx_tfm); - crypto_digest_init(tcp_conn->data_tx_tfm); - tcp_ctask->digest_count = 4; + BUG_ON(!conn->data_tx_tfm); + crypto_digest_init(conn->data_tx_tfm); + ctask->digest_count = 4; } static int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int rc = 0; int sent = 0; if (final) - crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest); + crypto_digest_final(conn->data_tx_tfm, (u8*)digest); - iscsi_buf_init_iov(buf, (char*)digest, 4); - rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); + iscsi_buf_init_virt(buf, (char*)digest, 4); + rc = iscsi_sendpage(conn, buf, &ctask->digest_count, &sent); if (rc) { - tcp_ctask->datadigest = *digest; - tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; + ctask->datadigest = *digest; + ctask->xmstate |= XMSTATE_DATA_DIGEST; } else - tcp_ctask->digest_count = 4; + ctask->digest_count = 4; return rc; } @@ -1203,19 +1453,21 @@ static void iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_r2t_info *r2t, int left) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data *hdr; + struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; int new_offset; - hdr = &r2t->dtask.hdr; + dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); + BUG_ON(!dtask); + hdr = &dtask->hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->solicit_datasn); r2t->solicit_datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr->itt; + memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr.itt; hdr->exp_statsn = r2t->exp_statsn; new_offset = r2t->data_offset + r2t->sent; hdr->offset = cpu_to_be32(new_offset); @@ -1229,98 +1481,181 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, } conn->dataout_pdus_cnt++; - iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, + iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); + r2t->dtask = dtask; + if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) { - BUG_ON(tcp_ctask->bad_sg == r2t->sg); + BUG_ON(ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); r2t->sg += 1; } else - iscsi_buf_init_iov(&tcp_ctask->sendbuf, + iscsi_buf_init_iov(&ctask->sendbuf, (char*)sc->request_buffer + new_offset, r2t->data_count); + + list_add(&dtask->item, &ctask->dataqueue); } static void iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_data *hdr; struct iscsi_data_task *dtask; - dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask; - iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr, - tcp_ctask->r2t_data_count); - iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, + dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); + BUG_ON(!dtask); + hdr = &dtask->hdr; + memset(hdr, 0, sizeof(struct iscsi_data)); + hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + hdr->datasn = cpu_to_be32(ctask->unsol_datasn); + ctask->unsol_datasn++; + hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; + memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr.itt; + hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); + hdr->offset = cpu_to_be32(ctask->total_length - + ctask->r2t_data_count - + ctask->unsol_count); + if (ctask->unsol_count > conn->max_xmit_dlength) { + hton24(hdr->dlength, conn->max_xmit_dlength); + ctask->data_count = conn->max_xmit_dlength; + hdr->flags = 0; + } else { + hton24(hdr->dlength, ctask->unsol_count); + ctask->data_count = ctask->unsol_count; + hdr->flags = ISCSI_FLAG_CMD_FINAL; + } + + iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); + + list_add(&dtask->item, &ctask->dataqueue); + + ctask->dtask = dtask; } /** - * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands + * iscsi_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands * @conn: iscsi connection * @ctask: scsi command task * @sc: scsi command **/ static void -iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) +iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, + struct scsi_cmnd *sc) { - struct scsi_cmnd *sc = ctask->sc; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_session *session = conn->session; - BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); + BUG_ON(__kfifo_len(ctask->r2tqueue)); - tcp_ctask->sent = 0; - tcp_ctask->sg_count = 0; + ctask->sc = sc; + ctask->conn = conn; + ctask->hdr.opcode = ISCSI_OP_SCSI_CMD; + ctask->hdr.flags = ISCSI_ATTR_SIMPLE; + int_to_scsilun(sc->device->lun, (struct scsi_lun *)ctask->hdr.lun); + ctask->hdr.itt = ctask->itt | (conn->id << CID_SHIFT) | + (session->age << AGE_SHIFT); + ctask->hdr.data_length = cpu_to_be32(sc->request_bufflen); + ctask->hdr.cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; + ctask->hdr.exp_statsn = cpu_to_be32(conn->exp_statsn); + memcpy(ctask->hdr.cdb, sc->cmnd, sc->cmd_len); + memset(&ctask->hdr.cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); + + ctask->mtask = NULL; + ctask->sent = 0; + ctask->sg_count = 0; + + ctask->total_length = sc->request_bufflen; if (sc->sc_data_direction == DMA_TO_DEVICE) { - tcp_ctask->xmstate = XMSTATE_W_HDR; - tcp_ctask->exp_r2tsn = 0; + ctask->exp_r2tsn = 0; + ctask->hdr.flags |= ISCSI_FLAG_CMD_WRITE; BUG_ON(ctask->total_length == 0); - if (sc->use_sg) { struct scatterlist *sg = sc->request_buffer; - iscsi_buf_init_sg(&tcp_ctask->sendbuf, - &sg[tcp_ctask->sg_count++]); - tcp_ctask->sg = sg; - tcp_ctask->bad_sg = sg + sc->use_sg; - } else - iscsi_buf_init_iov(&tcp_ctask->sendbuf, - sc->request_buffer, - sc->request_bufflen); - - if (ctask->imm_count) - tcp_ctask->xmstate |= XMSTATE_IMM_DATA; + iscsi_buf_init_sg(&ctask->sendbuf, + &sg[ctask->sg_count++]); + ctask->sg = sg; + ctask->bad_sg = sg + sc->use_sg; + } else { + iscsi_buf_init_iov(&ctask->sendbuf, sc->request_buffer, + sc->request_bufflen); + } - tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); - if (tcp_ctask->pad_count) { - tcp_ctask->pad_count = ISCSI_PAD_LEN - - tcp_ctask->pad_count; + /* + * Write counters: + * + * imm_count bytes to be sent right after + * SCSI PDU Header + * + * unsol_count bytes(as Data-Out) to be sent + * without R2T ack right after + * immediate data + * + * r2t_data_count bytes to be sent via R2T ack's + * + * pad_count bytes to be sent as zero-padding + */ + ctask->imm_count = 0; + ctask->unsol_count = 0; + ctask->unsol_datasn = 0; + ctask->xmstate = XMSTATE_W_HDR; + /* calculate write padding */ + ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); + if (ctask->pad_count) { + ctask->pad_count = ISCSI_PAD_LEN - ctask->pad_count; debug_scsi("write padding %d bytes\n", - tcp_ctask->pad_count); - tcp_ctask->xmstate |= XMSTATE_W_PAD; + ctask->pad_count); + ctask->xmstate |= XMSTATE_W_PAD; } + if (session->imm_data_en) { + if (ctask->total_length >= session->first_burst) + ctask->imm_count = min(session->first_burst, + conn->max_xmit_dlength); + else + ctask->imm_count = min(ctask->total_length, + conn->max_xmit_dlength); + hton24(ctask->hdr.dlength, ctask->imm_count); + ctask->xmstate |= XMSTATE_IMM_DATA; + } else + zero_data(ctask->hdr.dlength); + + if (!session->initial_r2t_en) + ctask->unsol_count = min(session->first_burst, + ctask->total_length) - ctask->imm_count; + if (!ctask->unsol_count) + /* No unsolicit Data-Out's */ + ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL; + else + ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; - if (ctask->unsol_count) - tcp_ctask->xmstate |= XMSTATE_UNS_HDR | - XMSTATE_UNS_INIT; - tcp_ctask->r2t_data_count = ctask->total_length - + ctask->r2t_data_count = ctask->total_length - ctask->imm_count - ctask->unsol_count; debug_scsi("cmd [itt %x total %d imm %d imm_data %d " "r2t_data %d]\n", ctask->itt, ctask->total_length, ctask->imm_count, - ctask->unsol_count, tcp_ctask->r2t_data_count); - } else - tcp_ctask->xmstate = XMSTATE_R_HDR; + ctask->unsol_count, ctask->r2t_data_count); + } else { + ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL; + if (sc->sc_data_direction == DMA_FROM_DEVICE) + ctask->hdr.flags |= ISCSI_FLAG_CMD_READ; + ctask->datasn = 0; + ctask->xmstate = XMSTATE_R_HDR; + zero_data(ctask->hdr.dlength); + } - iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, + iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, sizeof(struct iscsi_hdr)); + conn->scsicmd_pdus_cnt++; } /** - * iscsi_tcp_mtask_xmit - xmit management(immediate) task + * iscsi_mtask_xmit - xmit management(immediate) task * @conn: iscsi connection * @mtask: task management task * @@ -1334,167 +1669,132 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) * IN_PROGRESS_IMM_DATA - PDU Data xmit in progress **/ static int -iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) +iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { - struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - int rc; debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", - conn->id, tcp_mtask->xmstate, mtask->itt); + conn->id, mtask->xmstate, mtask->itt); - if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { - tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; + if (mtask->xmstate & XMSTATE_IMM_HDR) { + mtask->xmstate &= ~XMSTATE_IMM_HDR; if (mtask->data_count) - tcp_mtask->xmstate |= XMSTATE_IMM_DATA; + mtask->xmstate |= XMSTATE_IMM_DATA; if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && - conn->stop_stage != STOP_CONN_RECOVER && + conn->stop_stage != STOP_CONN_RECOVER && conn->hdrdgst_en) - iscsi_hdr_digest(conn, &tcp_mtask->headbuf, - (u8*)tcp_mtask->hdrext); - rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, - mtask->data_count); - if (rc) { - tcp_mtask->xmstate |= XMSTATE_IMM_HDR; + iscsi_hdr_digest(conn, &mtask->headbuf, + (u8*)mtask->hdrext); + if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) { + mtask->xmstate |= XMSTATE_IMM_HDR; if (mtask->data_count) - tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; - return rc; + mtask->xmstate &= ~XMSTATE_IMM_DATA; + return -EAGAIN; } } - if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { + if (mtask->xmstate & XMSTATE_IMM_DATA) { BUG_ON(!mtask->data_count); - tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; + mtask->xmstate &= ~XMSTATE_IMM_DATA; /* FIXME: implement. * Virtual buffer could be spreaded across multiple pages... */ do { - int rc; - - rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, - &mtask->data_count, &tcp_mtask->sent); - if (rc) { - tcp_mtask->xmstate |= XMSTATE_IMM_DATA; - return rc; + if (iscsi_sendpage(conn, &mtask->sendbuf, + &mtask->data_count, &mtask->sent)) { + mtask->xmstate |= XMSTATE_IMM_DATA; + return -EAGAIN; } } while (mtask->data_count); } - BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); - if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) { - struct iscsi_session *session = conn->session; - - spin_lock_bh(&session->lock); - list_del(&conn->mtask->running); - __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, - sizeof(void*)); - spin_unlock_bh(&session->lock); - } + BUG_ON(mtask->xmstate != XMSTATE_IDLE); return 0; } static inline int -handle_xmstate_r_hdr(struct iscsi_conn *conn, - struct iscsi_tcp_cmd_task *tcp_ctask) +handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - int rc; - - tcp_ctask->xmstate &= ~XMSTATE_R_HDR; + ctask->xmstate &= ~XMSTATE_R_HDR; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &tcp_ctask->headbuf, - (u8*)tcp_ctask->hdrext); - rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0); - if (!rc) { - BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); + iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); + if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { + BUG_ON(ctask->xmstate != XMSTATE_IDLE); return 0; /* wait for Data-In */ } - tcp_ctask->xmstate |= XMSTATE_R_HDR; - return rc; + ctask->xmstate |= XMSTATE_R_HDR; + return -EAGAIN; } static inline int -handle_xmstate_w_hdr(struct iscsi_conn *conn, - struct iscsi_cmd_task *ctask) +handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - int rc; - - tcp_ctask->xmstate &= ~XMSTATE_W_HDR; + ctask->xmstate &= ~XMSTATE_W_HDR; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &tcp_ctask->headbuf, - (u8*)tcp_ctask->hdrext); - rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); - if (rc) - tcp_ctask->xmstate |= XMSTATE_W_HDR; - return rc; + iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); + if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { + ctask->xmstate |= XMSTATE_W_HDR; + return -EAGAIN; + } + return 0; } static inline int handle_xmstate_data_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - int rc; - - tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; - debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); - rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, - &tcp_ctask->datadigest, 0); - if (rc) { - tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; + ctask->xmstate &= ~XMSTATE_DATA_DIGEST; + debug_tcp("resent data digest 0x%x\n", ctask->datadigest); + if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, + &ctask->datadigest, 0)) { + ctask->xmstate |= XMSTATE_DATA_DIGEST; debug_tcp("resent data digest 0x%x fail!\n", - tcp_ctask->datadigest); + ctask->datadigest); + return -EAGAIN; } - - return rc; + return 0; } static inline int handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - int rc; - BUG_ON(!ctask->imm_count); - tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; + ctask->xmstate &= ~XMSTATE_IMM_DATA; if (conn->datadgst_en) { - iscsi_data_digest_init(tcp_conn, ctask); - tcp_ctask->immdigest = 0; + iscsi_data_digest_init(conn, ctask); + ctask->immdigest = 0; } for (;;) { - rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, - &ctask->imm_count, &tcp_ctask->sent); - if (rc) { - tcp_ctask->xmstate |= XMSTATE_IMM_DATA; + if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->imm_count, + &ctask->sent)) { + ctask->xmstate |= XMSTATE_IMM_DATA; if (conn->datadgst_en) { - crypto_digest_final(tcp_conn->data_tx_tfm, - (u8*)&tcp_ctask->immdigest); + crypto_digest_final(conn->data_tx_tfm, + (u8*)&ctask->immdigest); debug_tcp("tx imm sendpage fail 0x%x\n", - tcp_ctask->datadigest); + ctask->datadigest); } - return rc; + return -EAGAIN; } if (conn->datadgst_en) - crypto_digest_update(tcp_conn->data_tx_tfm, - &tcp_ctask->sendbuf.sg, 1); + crypto_digest_update(conn->data_tx_tfm, + &ctask->sendbuf.sg, 1); if (!ctask->imm_count) break; - iscsi_buf_init_sg(&tcp_ctask->sendbuf, - &tcp_ctask->sg[tcp_ctask->sg_count++]); + iscsi_buf_init_sg(&ctask->sendbuf, + &ctask->sg[ctask->sg_count++]); } - if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { - rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, - &tcp_ctask->immdigest, 1); - if (rc) { + if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) { + if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, + &ctask->immdigest, 1)) { debug_tcp("sending imm digest 0x%x fail!\n", - tcp_ctask->immdigest); - return rc; + ctask->immdigest); + return -EAGAIN; } - debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); + debug_tcp("sending imm digest 0x%x\n", ctask->immdigest); } return 0; @@ -1503,81 +1803,74 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) static inline int handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; - int rc; - tcp_ctask->xmstate |= XMSTATE_UNS_DATA; - if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { + ctask->xmstate |= XMSTATE_UNS_DATA; + if (ctask->xmstate & XMSTATE_UNS_INIT) { iscsi_unsolicit_data_init(conn, ctask); - dtask = tcp_ctask->dtask; + BUG_ON(!ctask->dtask); + dtask = ctask->dtask; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &tcp_ctask->headbuf, + iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)dtask->hdrext); - tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; + ctask->xmstate &= ~XMSTATE_UNS_INIT; } - - rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); - if (rc) { - tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; - tcp_ctask->xmstate |= XMSTATE_UNS_HDR; - return rc; + if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) { + ctask->xmstate &= ~XMSTATE_UNS_DATA; + ctask->xmstate |= XMSTATE_UNS_HDR; + return -EAGAIN; } debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", - ctask->itt, ctask->unsol_count, tcp_ctask->sent); + ctask->itt, ctask->unsol_count, ctask->sent); return 0; } static inline int handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_data_task *dtask = tcp_ctask->dtask; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - int rc; + struct iscsi_data_task *dtask = ctask->dtask; BUG_ON(!ctask->data_count); - tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; + ctask->xmstate &= ~XMSTATE_UNS_DATA; if (conn->datadgst_en) { - iscsi_data_digest_init(tcp_conn, ctask); + iscsi_data_digest_init(conn, ctask); dtask->digest = 0; } for (;;) { - int start = tcp_ctask->sent; + int start = ctask->sent; - rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, - &ctask->data_count, &tcp_ctask->sent); - if (rc) { - ctask->unsol_count -= tcp_ctask->sent - start; - tcp_ctask->xmstate |= XMSTATE_UNS_DATA; + if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->data_count, + &ctask->sent)) { + ctask->unsol_count -= ctask->sent - start; + ctask->xmstate |= XMSTATE_UNS_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_digest_final(tcp_conn->data_tx_tfm, + crypto_digest_final(conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("tx uns data fail 0x%x\n", dtask->digest); } - return rc; + return -EAGAIN; } - BUG_ON(tcp_ctask->sent > ctask->total_length); - ctask->unsol_count -= tcp_ctask->sent - start; + BUG_ON(ctask->sent > ctask->total_length); + ctask->unsol_count -= ctask->sent - start; /* * XXX:we may run here with un-initial sendbuf. * so pass it */ - if (conn->datadgst_en && tcp_ctask->sent - start > 0) - crypto_digest_update(tcp_conn->data_tx_tfm, - &tcp_ctask->sendbuf.sg, 1); + if (conn->datadgst_en && ctask->sent - start > 0) + crypto_digest_update(conn->data_tx_tfm, + &ctask->sendbuf.sg, 1); if (!ctask->data_count) break; - iscsi_buf_init_sg(&tcp_ctask->sendbuf, - &tcp_ctask->sg[tcp_ctask->sg_count++]); + iscsi_buf_init_sg(&ctask->sendbuf, + &ctask->sg[ctask->sg_count++]); } BUG_ON(ctask->unsol_count < 0); @@ -1587,29 +1880,27 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) */ if (ctask->unsol_count) { if (conn->datadgst_en) { - rc = iscsi_digest_final_send(conn, ctask, + if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1); - if (rc) { + &dtask->digest, 1)) { debug_tcp("send uns digest 0x%x fail\n", dtask->digest); - return rc; + return -EAGAIN; } debug_tcp("sending uns digest 0x%x, more uns\n", dtask->digest); } - tcp_ctask->xmstate |= XMSTATE_UNS_INIT; + ctask->xmstate |= XMSTATE_UNS_INIT; return 1; } - if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { - rc = iscsi_digest_final_send(conn, ctask, + if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) { + if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1); - if (rc) { + &dtask->digest, 1)) { debug_tcp("send last uns digest 0x%x fail\n", dtask->digest); - return rc; + return -EAGAIN; } debug_tcp("sending uns digest 0x%x\n",dtask->digest); } @@ -1621,17 +1912,15 @@ static inline int handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_session *session = conn->session; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_r2t_info *r2t = tcp_ctask->r2t; - struct iscsi_data_task *dtask = &r2t->dtask; - int left, rc; + struct iscsi_r2t_info *r2t = ctask->r2t; + struct iscsi_data_task *dtask = r2t->dtask; + int left; - tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; - tcp_ctask->dtask = dtask; + ctask->xmstate &= ~XMSTATE_SOL_DATA; + ctask->dtask = dtask; if (conn->datadgst_en) { - iscsi_data_digest_init(tcp_conn, ctask); + iscsi_data_digest_init(conn, ctask); dtask->digest = 0; } solicit_again: @@ -1641,27 +1930,25 @@ solicit_again: if (!r2t->data_count) goto data_out_done; - rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent); - if (rc) { - tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) { + ctask->xmstate |= XMSTATE_SOL_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_digest_final(tcp_conn->data_tx_tfm, + crypto_digest_final(conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("r2t data send fail 0x%x\n", dtask->digest); } - return rc; + return -EAGAIN; } BUG_ON(r2t->data_count < 0); if (conn->datadgst_en) - crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg, - 1); + crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); if (r2t->data_count) { BUG_ON(ctask->sc->use_sg == 0); if (!iscsi_buf_left(&r2t->sendbuf)) { - BUG_ON(tcp_ctask->bad_sg == r2t->sg); + BUG_ON(ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); r2t->sg += 1; } @@ -1677,20 +1964,19 @@ data_out_done: left = r2t->data_length - r2t->sent; if (left) { if (conn->datadgst_en) { - rc = iscsi_digest_final_send(conn, ctask, + if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1); - if (rc) { + &dtask->digest, 1)) { debug_tcp("send r2t data digest 0x%x" "fail\n", dtask->digest); - return rc; + return -EAGAIN; } debug_tcp("r2t data send digest 0x%x\n", dtask->digest); } iscsi_solicit_data_cont(conn, ctask, r2t, left); - tcp_ctask->xmstate |= XMSTATE_SOL_DATA; - tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; + ctask->xmstate |= XMSTATE_SOL_DATA; + ctask->xmstate &= ~XMSTATE_SOL_HDR; return 1; } @@ -1698,27 +1984,26 @@ data_out_done: * Done with this R2T. Check if there are more * outstanding R2Ts ready to be processed. */ - BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0); + BUG_ON(ctask->r2t_data_count - r2t->data_length < 0); if (conn->datadgst_en) { - rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1); - if (rc) { + if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, + &dtask->digest, 1)) { debug_tcp("send last r2t data digest 0x%x" "fail\n", dtask->digest); - return rc; + return -EAGAIN; } debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); } - tcp_ctask->r2t_data_count -= r2t->data_length; - tcp_ctask->r2t = NULL; + ctask->r2t_data_count -= r2t->data_length; + ctask->r2t = NULL; spin_lock_bh(&session->lock); - __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); spin_unlock_bh(&session->lock); - if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { - tcp_ctask->r2t = r2t; - tcp_ctask->xmstate |= XMSTATE_SOL_DATA; - tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; + if (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { + ctask->r2t = r2t; + ctask->xmstate |= XMSTATE_SOL_DATA; + ctask->xmstate &= ~XMSTATE_SOL_HDR; return 1; } @@ -1728,44 +2013,36 @@ data_out_done: static inline int handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct iscsi_data_task *dtask = tcp_ctask->dtask; - int sent, rc; - - tcp_ctask->xmstate &= ~XMSTATE_W_PAD; - iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, - tcp_ctask->pad_count); - rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, - &sent); - if (rc) { - tcp_ctask->xmstate |= XMSTATE_W_PAD; - return rc; + struct iscsi_data_task *dtask = ctask->dtask; + int sent; + + ctask->xmstate &= ~XMSTATE_W_PAD; + iscsi_buf_init_virt(&ctask->sendbuf, (char*)&ctask->pad, + ctask->pad_count); + if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->pad_count, &sent)) { + ctask->xmstate |= XMSTATE_W_PAD; + return -EAGAIN; } if (conn->datadgst_en) { - crypto_digest_update(tcp_conn->data_tx_tfm, - &tcp_ctask->sendbuf.sg, 1); + crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { - rc = iscsi_digest_final_send(conn, ctask, - &tcp_ctask->immbuf, - &tcp_ctask->immdigest, 1); - if (rc) { + if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, + &ctask->immdigest, 1)) { debug_tcp("send padding digest 0x%x" - "fail!\n", tcp_ctask->immdigest); - return rc; + "fail!\n", ctask->immdigest); + return -EAGAIN; } debug_tcp("done with padding, digest 0x%x\n", - tcp_ctask->datadigest); + ctask->datadigest); } else { - rc = iscsi_digest_final_send(conn, ctask, + if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1); - if (rc) { + &dtask->digest, 1)) { debug_tcp("send padding digest 0x%x" "fail\n", dtask->digest); - return rc; + return -EAGAIN; } debug_tcp("done with padding, digest 0x%x\n", dtask->digest); @@ -1776,13 +2053,12 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } static int -iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc = 0; debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n", - conn->id, tcp_ctask->xmstate, ctask->itt); + conn->id, ctask->xmstate, ctask->itt); /* * serialize with TMF AbortTask @@ -1790,38 +2066,40 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (ctask->mtask) return rc; - if (tcp_ctask->xmstate & XMSTATE_R_HDR) - return handle_xmstate_r_hdr(conn, tcp_ctask); + if (ctask->xmstate & XMSTATE_R_HDR) { + rc = handle_xmstate_r_hdr(conn, ctask); + return rc; + } - if (tcp_ctask->xmstate & XMSTATE_W_HDR) { + if (ctask->xmstate & XMSTATE_W_HDR) { rc = handle_xmstate_w_hdr(conn, ctask); if (rc) return rc; } /* XXX: for data digest xmit recover */ - if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) { + if (ctask->xmstate & XMSTATE_DATA_DIGEST) { rc = handle_xmstate_data_digest(conn, ctask); if (rc) return rc; } - if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { + if (ctask->xmstate & XMSTATE_IMM_DATA) { rc = handle_xmstate_imm_data(conn, ctask); if (rc) return rc; } - if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { + if (ctask->xmstate & XMSTATE_UNS_HDR) { BUG_ON(!ctask->unsol_count); - tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; + ctask->xmstate &= ~XMSTATE_UNS_HDR; unsolicit_head_again: rc = handle_xmstate_uns_hdr(conn, ctask); if (rc) return rc; } - if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { + if (ctask->xmstate & XMSTATE_UNS_DATA) { rc = handle_xmstate_uns_data(conn, ctask); if (rc == 1) goto unsolicit_head_again; @@ -1830,24 +2108,23 @@ unsolicit_head_again: goto done; } - if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { + if (ctask->xmstate & XMSTATE_SOL_HDR) { struct iscsi_r2t_info *r2t; - tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; - tcp_ctask->xmstate |= XMSTATE_SOL_DATA; - if (!tcp_ctask->r2t) - __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, + ctask->xmstate &= ~XMSTATE_SOL_HDR; + ctask->xmstate |= XMSTATE_SOL_DATA; + if (!ctask->r2t) + __kfifo_get(ctask->r2tqueue, (void*)&ctask->r2t, sizeof(void*)); solicit_head_again: - r2t = tcp_ctask->r2t; + r2t = ctask->r2t; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, - (u8*)r2t->dtask.hdrext); - rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); - if (rc) { - tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; - tcp_ctask->xmstate |= XMSTATE_SOL_HDR; - return rc; + (u8*)r2t->dtask->hdrext); + if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { + ctask->xmstate &= ~XMSTATE_SOL_DATA; + ctask->xmstate |= XMSTATE_SOL_HDR; + return -EAGAIN; } debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n", @@ -1855,7 +2132,7 @@ solicit_head_again: r2t->sent); } - if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { + if (ctask->xmstate & XMSTATE_SOL_DATA) { rc = handle_xmstate_sol_data(conn, ctask); if (rc == 1) goto solicit_head_again; @@ -1868,199 +2145,1022 @@ done: * Last thing to check is whether we need to send write * padding. Note that we check for xmstate equality, not just the bit. */ - if (tcp_ctask->xmstate == XMSTATE_W_PAD) + if (ctask->xmstate == XMSTATE_W_PAD) rc = handle_xmstate_w_pad(conn, ctask); return rc; } +/** + * iscsi_data_xmit - xmit any command into the scheduled connection + * @conn: iscsi connection + * + * Notes: + * The function can return -EAGAIN in which case the caller must + * re-schedule it again later or recover. '0' return code means + * successful xmit. + **/ +static int +iscsi_data_xmit(struct iscsi_conn *conn) +{ + if (unlikely(conn->suspend_tx)) { + debug_tcp("conn %d Tx suspended!\n", conn->id); + return 0; + } + + /* + * Transmit in the following order: + * + * 1) un-finished xmit (ctask or mtask) + * 2) immediate control PDUs + * 3) write data + * 4) SCSI commands + * 5) non-immediate control PDUs + * + * No need to lock around __kfifo_get as long as + * there's one producer and one consumer. + */ + + BUG_ON(conn->ctask && conn->mtask); + + if (conn->ctask) { + if (iscsi_ctask_xmit(conn, conn->ctask)) + goto again; + /* done with this in-progress ctask */ + conn->ctask = NULL; + } + if (conn->mtask) { + if (iscsi_mtask_xmit(conn, conn->mtask)) + goto again; + /* done with this in-progress mtask */ + conn->mtask = NULL; + } + + /* process immediate first */ + if (unlikely(__kfifo_len(conn->immqueue))) { + struct iscsi_session *session = conn->session; + while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, + sizeof(void*))) { + if (iscsi_mtask_xmit(conn, conn->mtask)) + goto again; + + if (conn->mtask->hdr.itt == + cpu_to_be32(ISCSI_RESERVED_TAG)) { + spin_lock_bh(&session->lock); + __kfifo_put(session->mgmtpool.queue, + (void*)&conn->mtask, sizeof(void*)); + spin_unlock_bh(&session->lock); + } + } + /* done with this mtask */ + conn->mtask = NULL; + } + + /* process write queue */ + while (__kfifo_get(conn->writequeue, (void*)&conn->ctask, + sizeof(void*))) { + if (iscsi_ctask_xmit(conn, conn->ctask)) + goto again; + } + + /* process command queue */ + while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, + sizeof(void*))) { + if (iscsi_ctask_xmit(conn, conn->ctask)) + goto again; + } + /* done with this ctask */ + conn->ctask = NULL; + + /* process the rest control plane PDUs, if any */ + if (unlikely(__kfifo_len(conn->mgmtqueue))) { + struct iscsi_session *session = conn->session; + + while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, + sizeof(void*))) { + if (iscsi_mtask_xmit(conn, conn->mtask)) + goto again; + + if (conn->mtask->hdr.itt == + cpu_to_be32(ISCSI_RESERVED_TAG)) { + spin_lock_bh(&session->lock); + __kfifo_put(session->mgmtpool.queue, + (void*)&conn->mtask, + sizeof(void*)); + spin_unlock_bh(&session->lock); + } + } + /* done with this mtask */ + conn->mtask = NULL; + } + + return 0; + +again: + if (unlikely(conn->suspend_tx)) + return 0; + + return -EAGAIN; +} + +static void +iscsi_xmitworker(void *data) +{ + struct iscsi_conn *conn = data; + + /* + * serialize Xmit worker on a per-connection basis. + */ + mutex_lock(&conn->xmitmutex); + if (iscsi_data_xmit(conn)) + scsi_queue_work(conn->session->host, &conn->xmitwork); + mutex_unlock(&conn->xmitmutex); +} + +#define FAILURE_BAD_HOST 1 +#define FAILURE_SESSION_FAILED 2 +#define FAILURE_SESSION_FREED 3 +#define FAILURE_WINDOW_CLOSED 4 +#define FAILURE_SESSION_TERMINATE 5 + +static int +iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host; + int reason = 0; + struct iscsi_session *session; + struct iscsi_conn *conn = NULL; + struct iscsi_cmd_task *ctask = NULL; + + sc->scsi_done = done; + sc->result = 0; + + host = sc->device->host; + session = iscsi_hostdata(host->hostdata); + BUG_ON(host != session->host); + + spin_lock(&session->lock); + + if (session->state != ISCSI_STATE_LOGGED_IN) { + if (session->state == ISCSI_STATE_FAILED) { + reason = FAILURE_SESSION_FAILED; + goto reject; + } else if (session->state == ISCSI_STATE_TERMINATE) { + reason = FAILURE_SESSION_TERMINATE; + goto fault; + } + reason = FAILURE_SESSION_FREED; + goto fault; + } + + /* + * Check for iSCSI window and take care of CmdSN wrap-around + */ + if ((int)(session->max_cmdsn - session->cmdsn) < 0) { + reason = FAILURE_WINDOW_CLOSED; + goto reject; + } + + conn = session->leadconn; + + __kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + BUG_ON(ctask->sc); + + sc->SCp.phase = session->age; + sc->SCp.ptr = (char*)ctask; + iscsi_cmd_init(conn, ctask, sc); + + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); + debug_scsi( + "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", + sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", + conn->id, (long)sc, ctask->itt, sc->request_bufflen, + session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); + spin_unlock(&session->lock); + + scsi_queue_work(host, &conn->xmitwork); + return 0; + +reject: + spin_unlock(&session->lock); + debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); + return SCSI_MLQUEUE_HOST_BUSY; + +fault: + spin_unlock(&session->lock); + printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", + sc->cmnd[0], reason); + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = NOT_READY; + sc->sense_buffer[7] = 0x6; + sc->sense_buffer[12] = 0x08; + sc->sense_buffer[13] = 0x00; + sc->result = (DID_NO_CONNECT << 16); + sc->resid = sc->request_bufflen; + sc->scsi_done(sc); + return 0; +} + +static int +iscsi_change_queue_depth(struct scsi_device *sdev, int depth) +{ + if (depth > ISCSI_MAX_CMD_PER_LUN) + depth = ISCSI_MAX_CMD_PER_LUN; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + return sdev->queue_depth; +} + +static int +iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) +{ + int i; + + *items = kmalloc(max * sizeof(void*), GFP_KERNEL); + if (*items == NULL) + return -ENOMEM; + + q->max = max; + q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL); + if (q->pool == NULL) { + kfree(*items); + return -ENOMEM; + } + + q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), + GFP_KERNEL, NULL); + if (q->queue == ERR_PTR(-ENOMEM)) { + kfree(q->pool); + kfree(*items); + return -ENOMEM; + } + + for (i = 0; i < max; i++) { + q->pool[i] = kmalloc(item_size, GFP_KERNEL); + if (q->pool[i] == NULL) { + int j; + + for (j = 0; j < i; j++) + kfree(q->pool[j]); + + kfifo_free(q->queue); + kfree(q->pool); + kfree(*items); + return -ENOMEM; + } + memset(q->pool[i], 0, item_size); + (*items)[i] = q->pool[i]; + __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); + } + return 0; +} + +static void +iscsi_pool_free(struct iscsi_queue *q, void **items) +{ + int i; + + for (i = 0; i < q->max; i++) + kfree(items[i]); + kfree(q->pool); + kfree(items); +} + static struct iscsi_cls_conn * -iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) +iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) { + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; - struct iscsi_tcp_conn *tcp_conn; - cls_conn = iscsi_conn_setup(cls_session, conn_idx); + cls_conn = iscsi_create_conn(cls_session, conn_idx); if (!cls_conn) return NULL; conn = cls_conn->dd_data; - /* - * due to strange issues with iser these are not set - * in iscsi_conn_setup - */ - conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + memset(conn, 0, sizeof(*conn)); - tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL); - if (!tcp_conn) - goto tcp_conn_alloc_fail; + conn->cls_conn = cls_conn; + conn->c_stage = ISCSI_CONN_INITIAL_STAGE; + conn->in_progress = IN_PROGRESS_WAIT_HEADER; + conn->id = conn_idx; + conn->exp_statsn = 0; + conn->tmabort_state = TMABORT_INITIAL; - conn->dd_data = tcp_conn; - tcp_conn->iscsi_conn = conn; - tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; /* initial operational parameters */ - tcp_conn->hdr_size = sizeof(struct iscsi_hdr); - tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + conn->hdr_size = sizeof(struct iscsi_hdr); + conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + + /* initialize general xmit PDU commands queue */ + conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->xmitqueue == ERR_PTR(-ENOMEM)) + goto xmitqueue_alloc_fail; + + /* initialize write response PDU commands queue */ + conn->writequeue = kfifo_alloc(session->cmds_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->writequeue == ERR_PTR(-ENOMEM)) + goto writequeue_alloc_fail; + + /* initialize general immediate & non-immediate PDU commands queue */ + conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->immqueue == ERR_PTR(-ENOMEM)) + goto immqueue_alloc_fail; + + conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) + goto mgmtqueue_alloc_fail; + + INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + + /* allocate login_mtask used for the login/text sequences */ + spin_lock_bh(&session->lock); + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&conn->login_mtask, + sizeof(void*))) { + spin_unlock_bh(&session->lock); + goto login_mtask_alloc_fail; + } + spin_unlock_bh(&session->lock); /* allocate initial PDU receive place holder */ - if (tcp_conn->data_size <= PAGE_SIZE) - tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL); + if (conn->data_size <= PAGE_SIZE) + conn->data = kmalloc(conn->data_size, GFP_KERNEL); else - tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL, - get_order(tcp_conn->data_size)); - if (!tcp_conn->data) + conn->data = (void*)__get_free_pages(GFP_KERNEL, + get_order(conn->data_size)); + if (!conn->data) goto max_recv_dlenght_alloc_fail; + init_timer(&conn->tmabort_timer); + mutex_init(&conn->xmitmutex); + init_waitqueue_head(&conn->ehwait); + return cls_conn; max_recv_dlenght_alloc_fail: - kfree(tcp_conn); -tcp_conn_alloc_fail: - iscsi_conn_teardown(cls_conn); + spin_lock_bh(&session->lock); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, + sizeof(void*)); + spin_unlock_bh(&session->lock); +login_mtask_alloc_fail: + kfifo_free(conn->mgmtqueue); +mgmtqueue_alloc_fail: + kfifo_free(conn->immqueue); +immqueue_alloc_fail: + kfifo_free(conn->writequeue); +writequeue_alloc_fail: + kfifo_free(conn->xmitqueue); +xmitqueue_alloc_fail: + iscsi_destroy_conn(cls_conn); return NULL; } static void -iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) +iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - int digest = 0; + struct iscsi_session *session = conn->session; + unsigned long flags; + + mutex_lock(&conn->xmitmutex); + set_bit(SUSPEND_BIT, &conn->suspend_tx); + if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { + struct sock *sk = conn->sock->sk; + + /* + * conn_start() has never been called! + * need to cleanup the socket. + */ + write_lock_bh(&sk->sk_callback_lock); + set_bit(SUSPEND_BIT, &conn->suspend_rx); + write_unlock_bh(&sk->sk_callback_lock); + + sock_hold(conn->sock->sk); + iscsi_conn_restore_callbacks(conn); + sock_put(conn->sock->sk); + sock_release(conn->sock); + conn->sock = NULL; + } - if (conn->hdrdgst_en || conn->datadgst_en) - digest = 1; + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; + if (session->leadconn == conn) { + /* + * leading connection? then give up on recovery. + */ + session->state = ISCSI_STATE_TERMINATE; + wake_up(&conn->ehwait); + } + spin_unlock_bh(&session->lock); + + mutex_unlock(&conn->xmitmutex); - iscsi_conn_teardown(cls_conn); + /* + * Block until all in-progress commands for this connection + * time out or fail. + */ + for (;;) { + spin_lock_irqsave(session->host->host_lock, flags); + if (!session->host->host_busy) { /* OK for ERL == 0 */ + spin_unlock_irqrestore(session->host->host_lock, flags); + break; + } + spin_unlock_irqrestore(session->host->host_lock, flags); + msleep_interruptible(500); + printk("conn_destroy(): host_busy %d host_failed %d\n", + session->host->host_busy, session->host->host_failed); + /* + * force eh_abort() to unblock + */ + wake_up(&conn->ehwait); + } - /* now free tcp_conn */ - if (digest) { - if (tcp_conn->tx_tfm) - crypto_free_tfm(tcp_conn->tx_tfm); - if (tcp_conn->rx_tfm) - crypto_free_tfm(tcp_conn->rx_tfm); - if (tcp_conn->data_tx_tfm) - crypto_free_tfm(tcp_conn->data_tx_tfm); - if (tcp_conn->data_rx_tfm) - crypto_free_tfm(tcp_conn->data_rx_tfm); + /* now free crypto */ + if (conn->hdrdgst_en || conn->datadgst_en) { + if (conn->tx_tfm) + crypto_free_tfm(conn->tx_tfm); + if (conn->rx_tfm) + crypto_free_tfm(conn->rx_tfm); + if (conn->data_tx_tfm) + crypto_free_tfm(conn->data_tx_tfm); + if (conn->data_rx_tfm) + crypto_free_tfm(conn->data_rx_tfm); } /* free conn->data, size = MaxRecvDataSegmentLength */ - if (tcp_conn->data_size <= PAGE_SIZE) - kfree(tcp_conn->data); + if (conn->data_size <= PAGE_SIZE) + kfree(conn->data); else - free_pages((unsigned long)tcp_conn->data, - get_order(tcp_conn->data_size)); - kfree(tcp_conn); + free_pages((unsigned long)conn->data, + get_order(conn->data_size)); + + spin_lock_bh(&session->lock); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, + sizeof(void*)); + list_del(&conn->item); + if (list_empty(&session->connections)) + session->leadconn = NULL; + if (session->leadconn && session->leadconn == conn) + session->leadconn = container_of(session->connections.next, + struct iscsi_conn, item); + + if (session->leadconn == NULL) + /* none connections exits.. reset sequencing */ + session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; + spin_unlock_bh(&session->lock); + + kfifo_free(conn->xmitqueue); + kfifo_free(conn->writequeue); + kfifo_free(conn->immqueue); + kfifo_free(conn->mgmtqueue); + + iscsi_destroy_conn(cls_conn); } static int -iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, - struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, - int is_leading) +iscsi_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint32_t transport_fd, + int is_leading) { - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; struct sock *sk; struct socket *sock; int err; /* lookup for existing socket */ - sock = sockfd_lookup((int)transport_eph, &err); + sock = sockfd_lookup(transport_fd, &err); if (!sock) { printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); return -EEXIST; } - err = iscsi_conn_bind(cls_session, cls_conn, is_leading); - if (err) - return err; + /* lookup for existing connection */ + spin_lock_bh(&session->lock); + list_for_each_entry(tmp, &session->connections, item) { + if (tmp == conn) { + if (conn->c_stage != ISCSI_CONN_STOPPED || + conn->stop_stage == STOP_CONN_TERM) { + printk(KERN_ERR "iscsi_tcp: can't bind " + "non-stopped connection (%d:%d)\n", + conn->c_stage, conn->stop_stage); + spin_unlock_bh(&session->lock); + return -EIO; + } + break; + } + } + if (tmp != conn) { + /* bind new iSCSI connection to session */ + conn->session = session; + + list_add(&conn->item, &session->connections); + } + spin_unlock_bh(&session->lock); - /* bind iSCSI connection and socket */ - tcp_conn->sock = sock; + if (conn->stop_stage != STOP_CONN_SUSPEND) { + /* bind iSCSI connection and socket */ + conn->sock = sock; - /* setup Socket parameters */ - sk = sock->sk; - sk->sk_reuse = 1; - sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ - sk->sk_allocation = GFP_ATOMIC; + /* setup Socket parameters */ + sk = sock->sk; + sk->sk_reuse = 1; + sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ + sk->sk_allocation = GFP_ATOMIC; - /* FIXME: disable Nagle's algorithm */ + /* FIXME: disable Nagle's algorithm */ + + /* + * Intercept TCP callbacks for sendfile like receive + * processing. + */ + iscsi_conn_set_callbacks(conn); + + conn->sendpage = conn->sock->ops->sendpage; + + /* + * set receive state machine into initial state + */ + conn->in_progress = IN_PROGRESS_WAIT_HEADER; + } + + if (is_leading) + session->leadconn = conn; /* - * Intercept TCP callbacks for sendfile like receive - * processing. - */ - conn->recv_lock = &sk->sk_callback_lock; - iscsi_conn_set_callbacks(conn); - tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; - /* - * set receive state machine into initial state + * Unblock xmitworker(), Login Phase will pass through. */ - tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; + clear_bit(SUSPEND_BIT, &conn->suspend_rx); + clear_bit(SUSPEND_BIT, &conn->suspend_tx); return 0; } -static void -iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +static int +iscsi_conn_start(struct iscsi_cls_conn *cls_conn) { - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_r2t_info *r2t; + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + struct sock *sk; - /* flush ctask's r2t queues */ - while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) - __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, - sizeof(void*)); + /* FF phase warming up... */ - __iscsi_ctask_cleanup(conn, ctask); + if (session == NULL) { + printk(KERN_ERR "iscsi_tcp: can't start unbound connection\n"); + return -EPERM; + } + + sk = conn->sock->sk; + + write_lock_bh(&sk->sk_callback_lock); + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_STARTED; + session->state = ISCSI_STATE_LOGGED_IN; + + switch(conn->stop_stage) { + case STOP_CONN_RECOVER: + /* + * unblock eh_abort() if it is blocked. re-try all + * commands after successful recovery + */ + session->conn_cnt++; + conn->stop_stage = 0; + conn->tmabort_state = TMABORT_INITIAL; + session->age++; + wake_up(&conn->ehwait); + break; + case STOP_CONN_TERM: + session->conn_cnt++; + conn->stop_stage = 0; + break; + case STOP_CONN_SUSPEND: + conn->stop_stage = 0; + clear_bit(SUSPEND_BIT, &conn->suspend_rx); + clear_bit(SUSPEND_BIT, &conn->suspend_tx); + break; + default: + break; + } + spin_unlock_bh(&session->lock); + write_unlock_bh(&sk->sk_callback_lock); + + return 0; } static void -iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) +iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; struct sock *sk; + unsigned long flags; - if (!tcp_conn->sock) - return; - - sk = tcp_conn->sock->sk; + BUG_ON(!conn->sock); + sk = conn->sock->sk; write_lock_bh(&sk->sk_callback_lock); - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + set_bit(SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&sk->sk_callback_lock); + + mutex_lock(&conn->xmitmutex); + + spin_lock_irqsave(session->host->host_lock, flags); + spin_lock(&session->lock); + conn->stop_stage = flag; + conn->c_stage = ISCSI_CONN_STOPPED; + set_bit(SUSPEND_BIT, &conn->suspend_tx); + + if (flag != STOP_CONN_SUSPEND) + session->conn_cnt--; + + if (session->conn_cnt == 0 || session->leadconn == conn) + session->state = ISCSI_STATE_FAILED; + + spin_unlock(&session->lock); + spin_unlock_irqrestore(session->host->host_lock, flags); + + if (flag == STOP_CONN_TERM || flag == STOP_CONN_RECOVER) { + struct iscsi_cmd_task *ctask; + struct iscsi_mgmt_task *mtask; + + /* + * Socket must go now. + */ + sock_hold(conn->sock->sk); + iscsi_conn_restore_callbacks(conn); + sock_put(conn->sock->sk); + + /* + * flush xmit queues. + */ + spin_lock_bh(&session->lock); + while (__kfifo_get(conn->writequeue, (void*)&ctask, + sizeof(void*)) || + __kfifo_get(conn->xmitqueue, (void*)&ctask, + sizeof(void*))) { + struct iscsi_r2t_info *r2t; + + /* + * flush ctask's r2t queues + */ + while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, + sizeof(void*))) + __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, + sizeof(void*)); + + spin_unlock_bh(&session->lock); + local_bh_disable(); + iscsi_ctask_cleanup(conn, ctask); + local_bh_enable(); + spin_lock_bh(&session->lock); + } + conn->ctask = NULL; + while (__kfifo_get(conn->immqueue, (void*)&mtask, + sizeof(void*)) || + __kfifo_get(conn->mgmtqueue, (void*)&mtask, + sizeof(void*))) { + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + } + conn->mtask = NULL; + spin_unlock_bh(&session->lock); + + /* + * release socket only after we stopped data_xmit() + * activity and flushed all outstandings + */ + sock_release(conn->sock); + conn->sock = NULL; + + /* + * for connection level recovery we should not calculate + * header digest. conn->hdr_size used for optimization + * in hdr_extract() and will be re-negotiated at + * set_param() time. + */ + if (flag == STOP_CONN_RECOVER) { + conn->hdr_size = sizeof(struct iscsi_hdr); + conn->hdrdgst_en = 0; + conn->datadgst_en = 0; + } + } + mutex_unlock(&conn->xmitmutex); } -static void -iscsi_tcp_terminate_conn(struct iscsi_conn *conn) +static int +iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_session *session = conn->session; + struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; + struct iscsi_mgmt_task *mtask; - if (!tcp_conn->sock) - return; + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_TERMINATE) { + spin_unlock_bh(&session->lock); + return -EPERM; + } + if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || + hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) + /* + * Login and Text are sent serially, in + * request-followed-by-response sequence. + * Same mtask can be used. Same ITT must be used. + * Note that login_mtask is preallocated at conn_create(). + */ + mtask = conn->login_mtask; + else { + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*))) { + spin_unlock_bh(&session->lock); + return -ENOSPC; + } + } + + /* + * pre-format CmdSN and ExpStatSN for outgoing PDU. + */ + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + hdr->itt = mtask->itt | (conn->id << CID_SHIFT) | + (session->age << AGE_SHIFT); + nop->cmdsn = cpu_to_be32(session->cmdsn); + if (conn->c_stage == ISCSI_CONN_STARTED && + !(hdr->opcode & ISCSI_OP_IMMEDIATE)) + session->cmdsn++; + } else + /* do not advance CmdSN */ + nop->cmdsn = cpu_to_be32(session->cmdsn); + + nop->exp_statsn = cpu_to_be32(conn->exp_statsn); + + memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr)); + + iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr, + sizeof(struct iscsi_hdr)); + + spin_unlock_bh(&session->lock); + + if (data_size) { + memcpy(mtask->data, data, data_size); + mtask->data_count = data_size; + } else + mtask->data_count = 0; + + mtask->xmstate = XMSTATE_IMM_HDR; + + if (mtask->data_count) { + iscsi_buf_init_iov(&mtask->sendbuf, (char*)mtask->data, + mtask->data_count); + } + + debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", + hdr->opcode, hdr->itt, data_size); - sock_hold(tcp_conn->sock->sk); - iscsi_conn_restore_callbacks(conn); - sock_put(tcp_conn->sock->sk); + /* + * since send_pdu() could be called at least from two contexts, + * we need to serialize __kfifo_put, so we don't have to take + * additional lock on fast data-path + */ + if (hdr->opcode & ISCSI_OP_IMMEDIATE) + __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); + else + __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); - sock_release(tcp_conn->sock); - tcp_conn->sock = NULL; - conn->recv_lock = NULL; + scsi_queue_work(session->host, &conn->xmitwork); + return 0; +} + +static int +iscsi_eh_host_reset(struct scsi_cmnd *sc) +{ + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_TERMINATE) { + debug_scsi("failing host reset: session terminated " + "[CID %d age %d]", conn->id, session->age); + spin_unlock_bh(&session->lock); + return FAILED; + } + spin_unlock_bh(&session->lock); + + debug_scsi("failing connection CID %d due to SCSI host reset " + "[itt 0x%x age %d]", conn->id, ctask->itt, + session->age); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + + return SUCCESS; } -/* called with host lock */ static void -iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, - char *data, uint32_t data_size) +iscsi_tmabort_timedout(unsigned long data) { - struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; - iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, - sizeof(struct iscsi_hdr)); - tcp_mtask->xmstate = XMSTATE_IMM_HDR; + spin_lock(&session->lock); + if (conn->tmabort_state == TMABORT_INITIAL) { + __kfifo_put(session->mgmtpool.queue, + (void*)&ctask->mtask, sizeof(void*)); + conn->tmabort_state = TMABORT_TIMEDOUT; + debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n", + (long)ctask->sc, ctask->itt); + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } + spin_unlock(&session->lock); +} - if (mtask->data_count) - iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, - mtask->data_count); +static int +iscsi_eh_abort(struct scsi_cmnd *sc) +{ + int rc; + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + + conn->eh_abort_cnt++; + debug_scsi("aborting [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + + /* + * two cases for ERL=0 here: + * + * 1) connection-level failure; + * 2) recovery due protocol error; + */ + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + if (session->state != ISCSI_STATE_LOGGED_IN) { + if (session->state == ISCSI_STATE_TERMINATE) { + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + goto failed; + } + spin_unlock_bh(&session->lock); + } else { + struct iscsi_tm *hdr = &conn->tmhdr; + + /* + * Still LOGGED_IN... + */ + + if (!ctask->sc || sc->SCp.phase != session->age) { + /* + * 1) ctask completed before time out. But session + * is still ok => Happy Retry. + * 2) session was re-open during time out of ctask. + */ + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + goto success; + } + conn->tmabort_state = TMABORT_INITIAL; + spin_unlock_bh(&session->lock); + + /* + * ctask timed out but session is OK + * ERL=0 requires task mgmt abort to be issued on each + * failed command. requests must be serialized. + */ + memset(hdr, 0, sizeof(struct iscsi_tm)); + hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; + hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); + hdr->rtt = ctask->hdr.itt; + hdr->refcmdsn = ctask->hdr.cmdsn; + + rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, + NULL, 0); + if (rc) { + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + debug_scsi("abort sent failure [itt 0x%x]", ctask->itt); + } else { + struct iscsi_r2t_info *r2t; + + /* + * TMF abort vs. TMF response race logic + */ + spin_lock_bh(&session->lock); + ctask->mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[(hdr->itt & ITT_MASK) - + ISCSI_MGMT_ITT_OFFSET]; + /* + * have to flush r2tqueue to avoid r2t leaks + */ + while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, + sizeof(void*))) { + __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, + sizeof(void*)); + } + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmfcmd_pdus_cnt++; + conn->tmabort_timer.expires = 3*HZ + jiffies; + conn->tmabort_timer.function = + iscsi_tmabort_timedout; + conn->tmabort_timer.data = (unsigned long)ctask; + add_timer(&conn->tmabort_timer); + debug_scsi("abort sent [itt 0x%x]", ctask->itt); + } else { + if (!ctask->sc || + conn->tmabort_state == TMABORT_SUCCESS) { + conn->tmabort_state = TMABORT_INITIAL; + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + goto success; + } + conn->tmabort_state = TMABORT_INITIAL; + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } + spin_unlock_bh(&session->lock); + } + } + mutex_unlock(&conn->xmitmutex); + + + /* + * block eh thread until: + * + * 1) abort response; + * 2) abort timeout; + * 3) session re-opened; + * 4) session terminated; + */ + for (;;) { + int p_state = session->state; + + rc = wait_event_interruptible(conn->ehwait, + (p_state == ISCSI_STATE_LOGGED_IN ? + (session->state == ISCSI_STATE_TERMINATE || + conn->tmabort_state != TMABORT_INITIAL) : + (session->state == ISCSI_STATE_TERMINATE || + session->state == ISCSI_STATE_LOGGED_IN))); + if (rc) { + /* shutdown.. */ + session->state = ISCSI_STATE_TERMINATE; + goto failed; + } + + if (signal_pending(current)) + flush_signals(current); + + if (session->state == ISCSI_STATE_TERMINATE) + goto failed; + + spin_lock_bh(&session->lock); + if (sc->SCp.phase == session->age && + (conn->tmabort_state == TMABORT_TIMEDOUT || + conn->tmabort_state == TMABORT_FAILED)) { + conn->tmabort_state = TMABORT_INITIAL; + if (!ctask->sc) { + /* + * ctask completed before tmf abort response or + * time out. + * But session is still ok => Happy Retry. + */ + spin_unlock_bh(&session->lock); + break; + } + spin_unlock_bh(&session->lock); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + continue; + } + spin_unlock_bh(&session->lock); + break; + } + +success: + debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + rc = SUCCESS; + goto exit; + +failed: + debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + rc = FAILED; + +exit: + del_timer_sync(&conn->tmabort_timer); + + mutex_lock(&conn->xmitmutex); + if (conn->sock) { + struct sock *sk = conn->sock->sk; + + write_lock_bh(&sk->sk_callback_lock); + iscsi_ctask_cleanup(conn, ctask); + write_unlock_bh(&sk->sk_callback_lock); + } + mutex_unlock(&conn->xmitmutex); + return rc; } static int @@ -2074,7 +3174,6 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) */ for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; /* * pre-allocated x4 as much r2ts to handle race when @@ -2083,32 +3182,42 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) */ /* R2T pool */ - if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, - (void***)&tcp_ctask->r2ts, - sizeof(struct iscsi_r2t_info))) { + if (iscsi_pool_init(&ctask->r2tpool, session->max_r2t * 4, + (void***)&ctask->r2ts, sizeof(struct iscsi_r2t_info))) { goto r2t_alloc_fail; } /* R2T xmit queue */ - tcp_ctask->r2tqueue = kfifo_alloc( + ctask->r2tqueue = kfifo_alloc( session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); - if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) { - iscsi_pool_free(&tcp_ctask->r2tpool, - (void**)tcp_ctask->r2ts); + if (ctask->r2tqueue == ERR_PTR(-ENOMEM)) { + iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts); goto r2t_alloc_fail; } + + /* + * number of + * Data-Out PDU's within R2T-sequence can be quite big; + * using mempool + */ + ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX, + taskcache); + if (ctask->datapool == NULL) { + kfifo_free(ctask->r2tqueue); + iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts); + goto r2t_alloc_fail; + } + INIT_LIST_HEAD(&ctask->dataqueue); } return 0; r2t_alloc_fail: for (i = 0; i < cmd_i; i++) { - struct iscsi_cmd_task *ctask = session->cmds[i]; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - - kfifo_free(tcp_ctask->r2tqueue); - iscsi_pool_free(&tcp_ctask->r2tpool, - (void**)tcp_ctask->r2ts); + mempool_destroy(session->cmds[i]->datapool); + kfifo_free(session->cmds[i]->r2tqueue); + iscsi_pool_free(&session->cmds[i]->r2tpool, + (void**)session->cmds[i]->r2ts); } return -ENOMEM; } @@ -2119,13 +3228,127 @@ iscsi_r2tpool_free(struct iscsi_session *session) int i; for (i = 0; i < session->cmds_max; i++) { - struct iscsi_cmd_task *ctask = session->cmds[i]; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + mempool_destroy(session->cmds[i]->datapool); + kfifo_free(session->cmds[i]->r2tqueue); + iscsi_pool_free(&session->cmds[i]->r2tpool, + (void**)session->cmds[i]->r2ts); + } +} + +static struct scsi_host_template iscsi_sht = { + .name = "iSCSI Initiator over TCP/IP, v." + ISCSI_VERSION_STR, + .queuecommand = iscsi_queuecommand, + .change_queue_depth = iscsi_change_queue_depth, + .can_queue = ISCSI_XMIT_CMDS_MAX - 1, + .sg_tablesize = ISCSI_SG_TABLESIZE, + .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, + .eh_abort_handler = iscsi_eh_abort, + .eh_host_reset_handler = iscsi_eh_host_reset, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "iscsi_tcp", + .this_id = -1, +}; + +static struct iscsi_transport iscsi_tcp_transport; + +static struct iscsi_cls_session * +iscsi_session_create(struct scsi_transport_template *scsit, + uint32_t initial_cmdsn, uint32_t *sid) +{ + struct Scsi_Host *shost; + struct iscsi_session *session; + int cmd_i; + + shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); + if (!shost) + return NULL; + + session = iscsi_hostdata(shost->hostdata); + memset(session, 0, sizeof(struct iscsi_session)); + session->host = shost; + session->state = ISCSI_STATE_FREE; + session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; + session->cmds_max = ISCSI_XMIT_CMDS_MAX; + session->cmdsn = initial_cmdsn; + session->exp_cmdsn = initial_cmdsn + 1; + session->max_cmdsn = initial_cmdsn + 1; + session->max_r2t = 1; + *sid = shost->host_no; + + /* initialize SCSI PDU commands pool */ + if (iscsi_pool_init(&session->cmdpool, session->cmds_max, + (void***)&session->cmds, sizeof(struct iscsi_cmd_task))) + goto cmdpool_alloc_fail; + + /* pre-format cmds pool with ITT */ + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) + session->cmds[cmd_i]->itt = cmd_i; + + spin_lock_init(&session->lock); + INIT_LIST_HEAD(&session->connections); + + /* initialize immediate command pool */ + if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, + (void***)&session->mgmt_cmds, sizeof(struct iscsi_mgmt_task))) + goto mgmtpool_alloc_fail; + + + /* pre-format immediate cmds pool with ITT */ + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { + session->mgmt_cmds[cmd_i]->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; + session->mgmt_cmds[cmd_i]->data = kmalloc( + DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); + if (!session->mgmt_cmds[cmd_i]->data) { + int j; + + for (j = 0; j < cmd_i; j++) + kfree(session->mgmt_cmds[j]->data); + goto immdata_alloc_fail; + } + } + + if (iscsi_r2tpool_alloc(session)) + goto r2tpool_alloc_fail; - kfifo_free(tcp_ctask->r2tqueue); - iscsi_pool_free(&tcp_ctask->r2tpool, - (void**)tcp_ctask->r2ts); + return hostdata_session(shost->hostdata); + +r2tpool_alloc_fail: + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) + kfree(session->mgmt_cmds[cmd_i]->data); +immdata_alloc_fail: + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); +mgmtpool_alloc_fail: + iscsi_pool_free(&session->cmdpool, (void**)session->cmds); +cmdpool_alloc_fail: + iscsi_transport_destroy_session(shost); + return NULL; +} + +static void +iscsi_session_destroy(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + int cmd_i; + struct iscsi_data_task *dtask, *n; + + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { + struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { + list_del(&dtask->item); + mempool_free(dtask, ctask->datapool); + } } + + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) + kfree(session->mgmt_cmds[cmd_i]->data); + + iscsi_r2tpool_free(session); + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); + iscsi_pool_free(&session->cmdpool, (void**)session->cmds); + + iscsi_transport_destroy_session(shost); } static int @@ -2134,14 +3357,23 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + + spin_lock_bh(&session->lock); + if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && + conn->stop_stage != STOP_CONN_RECOVER) { + printk(KERN_ERR "iscsi_tcp: can not change parameter [%d]\n", + param); + spin_unlock_bh(&session->lock); + return 0; + } + spin_unlock_bh(&session->lock); switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: { - char *saveptr = tcp_conn->data; + char *saveptr = conn->data; gfp_t flags = GFP_KERNEL; - if (tcp_conn->data_size >= value) { + if (conn->data_size >= value) { conn->max_recv_dlength = value; break; } @@ -2152,21 +3384,21 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, spin_unlock_bh(&session->lock); if (value <= PAGE_SIZE) - tcp_conn->data = kmalloc(value, flags); + conn->data = kmalloc(value, flags); else - tcp_conn->data = (void*)__get_free_pages(flags, + conn->data = (void*)__get_free_pages(flags, get_order(value)); - if (tcp_conn->data == NULL) { - tcp_conn->data = saveptr; + if (conn->data == NULL) { + conn->data = saveptr; return -ENOMEM; } - if (tcp_conn->data_size <= PAGE_SIZE) + if (conn->data_size <= PAGE_SIZE) kfree(saveptr); else free_pages((unsigned long)saveptr, - get_order(tcp_conn->data_size)); + get_order(conn->data_size)); conn->max_recv_dlength = value; - tcp_conn->data_size = value; + conn->data_size = value; } break; case ISCSI_PARAM_MAX_XMIT_DLENGTH: @@ -2174,51 +3406,49 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, break; case ISCSI_PARAM_HDRDGST_EN: conn->hdrdgst_en = value; - tcp_conn->hdr_size = sizeof(struct iscsi_hdr); + conn->hdr_size = sizeof(struct iscsi_hdr); if (conn->hdrdgst_en) { - tcp_conn->hdr_size += sizeof(__u32); - if (!tcp_conn->tx_tfm) - tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", - 0); - if (!tcp_conn->tx_tfm) + conn->hdr_size += sizeof(__u32); + if (!conn->tx_tfm) + conn->tx_tfm = crypto_alloc_tfm("crc32c", 0); + if (!conn->tx_tfm) return -ENOMEM; - if (!tcp_conn->rx_tfm) - tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", - 0); - if (!tcp_conn->rx_tfm) { - crypto_free_tfm(tcp_conn->tx_tfm); + if (!conn->rx_tfm) + conn->rx_tfm = crypto_alloc_tfm("crc32c", 0); + if (!conn->rx_tfm) { + crypto_free_tfm(conn->tx_tfm); return -ENOMEM; } } else { - if (tcp_conn->tx_tfm) - crypto_free_tfm(tcp_conn->tx_tfm); - if (tcp_conn->rx_tfm) - crypto_free_tfm(tcp_conn->rx_tfm); + if (conn->tx_tfm) + crypto_free_tfm(conn->tx_tfm); + if (conn->rx_tfm) + crypto_free_tfm(conn->rx_tfm); } break; case ISCSI_PARAM_DATADGST_EN: conn->datadgst_en = value; if (conn->datadgst_en) { - if (!tcp_conn->data_tx_tfm) - tcp_conn->data_tx_tfm = + if (!conn->data_tx_tfm) + conn->data_tx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!tcp_conn->data_tx_tfm) + if (!conn->data_tx_tfm) return -ENOMEM; - if (!tcp_conn->data_rx_tfm) - tcp_conn->data_rx_tfm = + if (!conn->data_rx_tfm) + conn->data_rx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!tcp_conn->data_rx_tfm) { - crypto_free_tfm(tcp_conn->data_tx_tfm); + if (!conn->data_rx_tfm) { + crypto_free_tfm(conn->data_tx_tfm); return -ENOMEM; } } else { - if (tcp_conn->data_tx_tfm) - crypto_free_tfm(tcp_conn->data_tx_tfm); - if (tcp_conn->data_rx_tfm) - crypto_free_tfm(tcp_conn->data_rx_tfm); + if (conn->data_tx_tfm) + crypto_free_tfm(conn->data_tx_tfm); + if (conn->data_rx_tfm) + crypto_free_tfm(conn->data_rx_tfm); } - tcp_conn->sendpage = conn->datadgst_en ? - sock_no_sendpage : tcp_conn->sock->ops->sendpage; + conn->sendpage = conn->datadgst_en ? + sock_no_sendpage : conn->sock->ops->sendpage; break; case ISCSI_PARAM_INITIAL_R2T_EN: session->initial_r2t_en = value; @@ -2259,9 +3489,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, BUG_ON(value); session->ofmarker_en = value; break; - case ISCSI_PARAM_EXP_STATSN: - conn->exp_statsn = value; - break; default: break; } @@ -2308,7 +3535,7 @@ iscsi_session_get_param(struct iscsi_cls_session *cls_session, *value = session->ofmarker_en; break; default: - return -EINVAL; + return ISCSI_ERR_PARAM_NOT_FOUND; } return 0; @@ -2319,8 +3546,6 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, uint32_t *value) { struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct inet_sock *inet; switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: @@ -2335,70 +3560,17 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, case ISCSI_PARAM_DATADGST_EN: *value = conn->datadgst_en; break; - case ISCSI_PARAM_CONN_PORT: - mutex_lock(&conn->xmitmutex); - if (!tcp_conn->sock) { - mutex_unlock(&conn->xmitmutex); - return -EINVAL; - } - - inet = inet_sk(tcp_conn->sock->sk); - *value = be16_to_cpu(inet->dport); - mutex_unlock(&conn->xmitmutex); - case ISCSI_PARAM_EXP_STATSN: - *value = conn->exp_statsn; - break; default: - return -EINVAL; + return ISCSI_ERR_PARAM_NOT_FOUND; } return 0; } -static int -iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn, - enum iscsi_param param, char *buf) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct sock *sk; - struct inet_sock *inet; - struct ipv6_pinfo *np; - int len = 0; - - switch (param) { - case ISCSI_PARAM_CONN_ADDRESS: - mutex_lock(&conn->xmitmutex); - if (!tcp_conn->sock) { - mutex_unlock(&conn->xmitmutex); - return -EINVAL; - } - - sk = tcp_conn->sock->sk; - if (sk->sk_family == PF_INET) { - inet = inet_sk(sk); - len = sprintf(buf, "%u.%u.%u.%u\n", - NIPQUAD(inet->daddr)); - } else { - np = inet6_sk(sk); - len = sprintf(buf, - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(np->daddr)); - } - mutex_unlock(&conn->xmitmutex); - break; - default: - return -EINVAL; - } - - return len; -} - static void iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) { struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; stats->txdata_octets = conn->txdata_octets; stats->rxdata_octets = conn->rxdata_octets; @@ -2411,141 +3583,68 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; stats->custom_length = 3; strcpy(stats->custom[0].desc, "tx_sendpage_failures"); - stats->custom[0].value = tcp_conn->sendpage_failures_cnt; + stats->custom[0].value = conn->sendpage_failures_cnt; strcpy(stats->custom[1].desc, "rx_discontiguous_hdr"); - stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt; + stats->custom[1].value = conn->discontiguous_hdr_cnt; strcpy(stats->custom[2].desc, "eh_abort_cnt"); stats->custom[2].value = conn->eh_abort_cnt; } -static struct iscsi_cls_session * -iscsi_tcp_session_create(struct iscsi_transport *iscsit, - struct scsi_transport_template *scsit, - uint32_t initial_cmdsn, uint32_t *hostno) +static int +iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) { - struct iscsi_cls_session *cls_session; - struct iscsi_session *session; - uint32_t hn; - int cmd_i; - - cls_session = iscsi_session_setup(iscsit, scsit, - sizeof(struct iscsi_tcp_cmd_task), - sizeof(struct iscsi_tcp_mgmt_task), - initial_cmdsn, &hn); - if (!cls_session) - return NULL; - *hostno = hn; - - session = class_to_transport_session(cls_session); - for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { - struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - - ctask->hdr = &tcp_ctask->hdr; - } - - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { - struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; - struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - - mtask->hdr = &tcp_mtask->hdr; - } - - if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session))) - goto r2tpool_alloc_fail; - - return cls_session; + struct iscsi_conn *conn = cls_conn->dd_data; + int rc; -r2tpool_alloc_fail: - iscsi_session_teardown(cls_session); - return NULL; -} + mutex_lock(&conn->xmitmutex); + rc = iscsi_conn_send_generic(conn, hdr, data, data_size); + mutex_unlock(&conn->xmitmutex); -static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) -{ - iscsi_r2tpool_free(class_to_transport_session(cls_session)); - iscsi_session_teardown(cls_session); + return rc; } -static struct scsi_host_template iscsi_sht = { - .name = "iSCSI Initiator over TCP/IP, v" - ISCSI_TCP_VERSION, - .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, - .can_queue = ISCSI_XMIT_CMDS_MAX - 1, - .sg_tablesize = ISCSI_SG_TABLESIZE, - .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, - .eh_abort_handler = iscsi_eh_abort, - .eh_host_reset_handler = iscsi_eh_host_reset, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "iscsi_tcp", - .this_id = -1, -}; - static struct iscsi_transport iscsi_tcp_transport = { .owner = THIS_MODULE, .name = "tcp", .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST, - .param_mask = ISCSI_MAX_RECV_DLENGTH | - ISCSI_MAX_XMIT_DLENGTH | - ISCSI_HDRDGST_EN | - ISCSI_DATADGST_EN | - ISCSI_INITIAL_R2T_EN | - ISCSI_MAX_R2T | - ISCSI_IMM_DATA_EN | - ISCSI_FIRST_BURST | - ISCSI_MAX_BURST | - ISCSI_PDU_INORDER_EN | - ISCSI_DATASEQ_INORDER_EN | - ISCSI_ERL | - ISCSI_CONN_PORT | - ISCSI_CONN_ADDRESS | - ISCSI_EXP_STATSN, .host_template = &iscsi_sht, + .hostdata_size = sizeof(struct iscsi_session), .conndata_size = sizeof(struct iscsi_conn), .max_conn = 1, .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, - /* session management */ - .create_session = iscsi_tcp_session_create, - .destroy_session = iscsi_tcp_session_destroy, - /* connection management */ - .create_conn = iscsi_tcp_conn_create, - .bind_conn = iscsi_tcp_conn_bind, - .destroy_conn = iscsi_tcp_conn_destroy, + .create_session = iscsi_session_create, + .destroy_session = iscsi_session_destroy, + .create_conn = iscsi_conn_create, + .bind_conn = iscsi_conn_bind, + .destroy_conn = iscsi_conn_destroy, .set_param = iscsi_conn_set_param, .get_conn_param = iscsi_conn_get_param, - .get_conn_str_param = iscsi_conn_get_str_param, .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, - /* these are called as part of conn recovery */ - .suspend_conn_recv = iscsi_tcp_suspend_conn_rx, - .terminate_conn = iscsi_tcp_terminate_conn, - /* IO */ .send_pdu = iscsi_conn_send_pdu, .get_stats = iscsi_conn_get_stats, - .init_cmd_task = iscsi_tcp_cmd_init, - .init_mgmt_task = iscsi_tcp_mgmt_init, - .xmit_cmd_task = iscsi_tcp_ctask_xmit, - .xmit_mgmt_task = iscsi_tcp_mtask_xmit, - .cleanup_cmd_task = iscsi_tcp_cleanup_ctask, - /* recovery */ - .session_recovery_timedout = iscsi_session_recovery_timedout, }; static int __init iscsi_tcp_init(void) { if (iscsi_max_lun < 1) { - printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u\n", - iscsi_max_lun); + printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); return -EINVAL; } iscsi_tcp_transport.max_lun = iscsi_max_lun; + taskcache = kmem_cache_create("iscsi_taskcache", + sizeof(struct iscsi_data_task), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!taskcache) + return -ENOMEM; + if (!iscsi_register_transport(&iscsi_tcp_transport)) - return -ENODEV; + kmem_cache_destroy(taskcache); return 0; } @@ -2554,6 +3653,7 @@ static void __exit iscsi_tcp_exit(void) { iscsi_unregister_transport(&iscsi_tcp_transport); + kmem_cache_destroy(taskcache); } module_init(iscsi_tcp_init); diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 808302832..ba26741ac 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -2,8 +2,7 @@ * iSCSI Initiator TCP Transport * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman - * Copyright (C) 2005 - 2006 Mike Christie - * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2005 Mike Christie * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -22,7 +21,20 @@ #ifndef ISCSI_TCP_H #define ISCSI_TCP_H -#include +/* Session's states */ +#define ISCSI_STATE_FREE 1 +#define ISCSI_STATE_LOGGED_IN 2 +#define ISCSI_STATE_FAILED 3 +#define ISCSI_STATE_TERMINATE 4 + +/* Connection's states */ +#define ISCSI_CONN_INITIAL_STAGE 0 +#define ISCSI_CONN_STARTED 1 +#define ISCSI_CONN_STOPPED 2 +#define ISCSI_CONN_CLEANUP_WAIT 3 + +/* Connection suspend "bit" */ +#define SUSPEND_BIT 1 /* Socket's Receive state machine */ #define IN_PROGRESS_WAIT_HEADER 0x0 @@ -30,6 +42,12 @@ #define IN_PROGRESS_DATA_RECV 0x2 #define IN_PROGRESS_DDIGEST_RECV 0x3 +/* Task Mgmt states */ +#define TMABORT_INITIAL 0x0 +#define TMABORT_SUCCESS 0x1 +#define TMABORT_FAILED 0x2 +#define TMABORT_TIMEDOUT 0x3 + /* xmit state machine */ #define XMSTATE_IDLE 0x0 #define XMSTATE_R_HDR 0x1 @@ -44,14 +62,34 @@ #define XMSTATE_W_PAD 0x200 #define XMSTATE_DATA_DIGEST 0x400 +#define ISCSI_CONN_MAX 1 #define ISCSI_CONN_RCVBUF_MIN 262144 #define ISCSI_CONN_SNDBUF_MIN 262144 #define ISCSI_PAD_LEN 4 #define ISCSI_R2T_MAX 16 +#define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ +#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ +#define ISCSI_MGMT_ITT_OFFSET 0xa00 #define ISCSI_SG_TABLESIZE SG_ALL +#define ISCSI_DEF_CMD_PER_LUN 32 +#define ISCSI_MAX_CMD_PER_LUN 128 #define ISCSI_TCP_MAX_CMD_LEN 16 -struct socket; +#define ITT_MASK (0xfff) +#define CID_SHIFT 12 +#define CID_MASK (0xffff<removable && (cmd[0] != TEST_UNIT_READY)) { - printk(KERN_INFO "Device not ready. Make sure" - " there is a disc in the drive.\n"); + if (sdev->removable) break; - } case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 5569fdcfd..2730d507e 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -31,26 +31,31 @@ #include #include -#define ISCSI_SESSION_ATTRS 11 -#define ISCSI_CONN_ATTRS 11 -#define ISCSI_HOST_ATTRS 0 +#define ISCSI_SESSION_ATTRS 8 +#define ISCSI_CONN_ATTRS 6 struct iscsi_internal { - int daemon_pid; struct scsi_transport_template t; struct iscsi_transport *iscsi_transport; struct list_head list; - struct class_device cdev; + /* + * based on transport capabilities, at register time we set these + * bits to tell the transport class it wants attributes displayed + * in sysfs or that it can support different iSCSI Data-Path + * capabilities + */ + uint32_t param_mask; - struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1]; + struct class_device cdev; + /* + * We do not have any private or other attrs. + */ struct transport_container conn_cont; struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1]; struct transport_container session_cont; struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; }; -static int iscsi_session_nr; /* sysfs session id for next new session */ - /* * list of registered transports and lock that must * be held while accessing list. The iscsi_transport_lock must @@ -115,24 +120,6 @@ static struct attribute_group iscsi_transport_group = { .attrs = iscsi_transport_attrs, }; -static int iscsi_setup_host(struct transport_container *tc, struct device *dev, - struct class_device *cdev) -{ - struct Scsi_Host *shost = dev_to_shost(dev); - struct iscsi_host *ihost = shost->shost_data; - - memset(ihost, 0, sizeof(*ihost)); - INIT_LIST_HEAD(&ihost->sessions); - mutex_init(&ihost->mutex); - return 0; -} - -static DECLARE_TRANSPORT_CLASS(iscsi_host_class, - "iscsi_host", - iscsi_setup_host, - NULL, - NULL); - static DECLARE_TRANSPORT_CLASS(iscsi_session_class, "iscsi_session", NULL, @@ -146,6 +133,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, NULL); static struct sock *nls; +static int daemon_pid; static DEFINE_MUTEX(rx_queue_mutex); struct mempool_zone { @@ -177,23 +165,14 @@ static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); static DEFINE_SPINLOCK(connlock); -static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn) -{ - struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent); - return sess->sid; -} - -/* - * Returns the matching session to a given sid - */ -static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid) +static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle) { unsigned long flags; struct iscsi_cls_session *sess; spin_lock_irqsave(&sesslock, flags); list_for_each_entry(sess, &sesslist, sess_list) { - if (sess->sid == sid) { + if (sess == iscsi_ptr(handle)) { spin_unlock_irqrestore(&sesslock, flags); return sess; } @@ -202,17 +181,14 @@ static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid) return NULL; } -/* - * Returns the matching connection to a given sid / cid tuple - */ -static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid) +static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle) { unsigned long flags; struct iscsi_cls_conn *conn; spin_lock_irqsave(&connlock, flags); list_for_each_entry(conn, &connlist, conn_list) { - if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) { + if (conn == iscsi_ptr(handle)) { spin_unlock_irqrestore(&connlock, flags); return conn; } @@ -233,7 +209,6 @@ static void iscsi_session_release(struct device *dev) shost = iscsi_session_to_shost(session); scsi_host_put(shost); - kfree(session->targetname); kfree(session); module_put(transport->owner); } @@ -243,95 +218,30 @@ static int iscsi_is_session_dev(const struct device *dev) return dev->release == iscsi_session_release; } -static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, - uint id, uint lun) -{ - struct iscsi_host *ihost = shost->shost_data; - struct iscsi_cls_session *session; - - mutex_lock(&ihost->mutex); - list_for_each_entry(session, &ihost->sessions, host_list) { - if ((channel == SCAN_WILD_CARD || - channel == session->channel) && - (id == SCAN_WILD_CARD || id == session->target_id)) - scsi_scan_target(&session->dev, session->channel, - session->target_id, lun, 1); - } - mutex_unlock(&ihost->mutex); - - return 0; -} - -static void session_recovery_timedout(void *data) -{ - struct iscsi_cls_session *session = data; - - dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " - "out after %d secs\n", session->recovery_tmo); - - if (session->transport->session_recovery_timedout) - session->transport->session_recovery_timedout(session); - - scsi_target_unblock(&session->dev); -} - -void iscsi_unblock_session(struct iscsi_cls_session *session) -{ - if (!cancel_delayed_work(&session->recovery_work)) - flush_scheduled_work(); - scsi_target_unblock(&session->dev); -} -EXPORT_SYMBOL_GPL(iscsi_unblock_session); - -void iscsi_block_session(struct iscsi_cls_session *session) -{ - scsi_target_block(&session->dev); - schedule_delayed_work(&session->recovery_work, - session->recovery_tmo * HZ); -} -EXPORT_SYMBOL_GPL(iscsi_block_session); - /** * iscsi_create_session - create iscsi class session * @shost: scsi host * @transport: iscsi transport * - * This can be called from a LLD or iscsi_transport. + * This can be called from a LLD or iscsi_transport **/ struct iscsi_cls_session * -iscsi_create_session(struct Scsi_Host *shost, - struct iscsi_transport *transport, int channel) +iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) { - struct iscsi_host *ihost; struct iscsi_cls_session *session; int err; if (!try_module_get(transport->owner)) return NULL; - session = kzalloc(sizeof(*session) + transport->sessiondata_size, - GFP_KERNEL); + session = kzalloc(sizeof(*session), GFP_KERNEL); if (!session) goto module_put; session->transport = transport; - session->recovery_tmo = 120; - INIT_WORK(&session->recovery_work, session_recovery_timedout, session); - INIT_LIST_HEAD(&session->host_list); - INIT_LIST_HEAD(&session->sess_list); - - if (transport->sessiondata_size) - session->dd_data = &session[1]; /* this is released in the dev's release function */ scsi_host_get(shost); - ihost = shost->shost_data; - - session->sid = iscsi_session_nr++; - session->channel = channel; - session->target_id = ihost->next_target_id++; - - snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", - session->sid); + snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); session->dev.parent = &shost->shost_gendev; session->dev.release = iscsi_session_release; err = device_register(&session->dev); @@ -342,10 +252,6 @@ iscsi_create_session(struct Scsi_Host *shost, } transport_register_device(&session->dev); - mutex_lock(&ihost->mutex); - list_add(&session->host_list, &ihost->sessions); - mutex_unlock(&ihost->mutex); - return session; free_session: @@ -366,16 +272,6 @@ EXPORT_SYMBOL_GPL(iscsi_create_session); **/ int iscsi_destroy_session(struct iscsi_cls_session *session) { - struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_host *ihost = shost->shost_data; - - if (!cancel_delayed_work(&session->recovery_work)) - flush_scheduled_work(); - - mutex_lock(&ihost->mutex); - list_del(&session->host_list); - mutex_unlock(&ihost->mutex); - transport_unregister_device(&session->dev); device_unregister(&session->dev); return 0; @@ -388,7 +284,6 @@ static void iscsi_conn_release(struct device *dev) struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); struct device *parent = conn->dev.parent; - kfree(conn->persistent_address); kfree(conn); put_device(parent); } @@ -406,16 +301,12 @@ static int iscsi_is_conn_dev(const struct device *dev) * This can be called from a LLD or iscsi_transport. The connection * is child of the session so cid must be unique for all connections * on the session. - * - * Since we do not support MCS, cid will normally be zero. In some cases - * for software iscsi we could be trying to preallocate a connection struct - * in which case there could be two connection structs and cid would be - * non-zero. **/ struct iscsi_cls_conn * iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) { struct iscsi_transport *transport = session->transport; + struct Scsi_Host *shost = iscsi_session_to_shost(session); struct iscsi_cls_conn *conn; int err; @@ -428,14 +319,12 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) INIT_LIST_HEAD(&conn->conn_list); conn->transport = transport; - conn->cid = cid; /* this is released in the dev's release function */ if (!get_device(&session->dev)) goto free_conn; - snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", - session->sid, cid); + shost->host_no, cid); conn->dev.parent = &session->dev; conn->dev.release = iscsi_conn_release; err = device_register(&conn->dev); @@ -471,6 +360,105 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) EXPORT_SYMBOL_GPL(iscsi_destroy_conn); +/* + * These functions are used only by software iscsi_transports + * which do not allocate and more their scsi_hosts since this + * is initiated from userspace. + */ + +/* + * iSCSI Session's hostdata organization: + * + * *------------------* <== hostdata_session(host->hostdata) + * | ptr to class sess| + * |------------------| <== iscsi_hostdata(host->hostdata) + * | transport's data | + * *------------------* + */ + +#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ + _t->hostdata_size % sizeof(unsigned long)) + +#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) + +/** + * iscsi_transport_create_session - create iscsi cls session and host + * scsit: scsi transport template + * transport: iscsi transport template + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +struct Scsi_Host * +iscsi_transport_create_session(struct scsi_transport_template *scsit, + struct iscsi_transport *transport) +{ + struct iscsi_cls_session *session; + struct Scsi_Host *shost; + unsigned long flags; + + shost = scsi_host_alloc(transport->host_template, + hostdata_privsize(transport)); + if (!shost) { + printk(KERN_ERR "iscsi: can not allocate SCSI host for " + "session\n"); + return NULL; + } + + shost->max_id = 1; + shost->max_channel = 0; + shost->max_lun = transport->max_lun; + shost->max_cmd_len = transport->max_cmd_len; + shost->transportt = scsit; + shost->transportt->create_work_queue = 1; + + if (scsi_add_host(shost, NULL)) + goto free_host; + + session = iscsi_create_session(shost, transport); + if (!session) + goto remove_host; + + *(unsigned long*)shost->hostdata = (unsigned long)session; + spin_lock_irqsave(&sesslock, flags); + list_add(&session->sess_list, &sesslist); + spin_unlock_irqrestore(&sesslock, flags); + return shost; + +remove_host: + scsi_remove_host(shost); +free_host: + scsi_host_put(shost); + return NULL; +} + +EXPORT_SYMBOL_GPL(iscsi_transport_create_session); + +/** + * iscsi_transport_destroy_session - destroy session and scsi host + * shost: scsi host + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +int iscsi_transport_destroy_session(struct Scsi_Host *shost) +{ + struct iscsi_cls_session *session; + unsigned long flags; + + scsi_remove_host(shost); + session = hostdata_session(shost->hostdata); + spin_lock_irqsave(&sesslock, flags); + list_del(&session->sess_list); + spin_unlock_irqrestore(&sesslock, flags); + iscsi_destroy_session(session); + /* ref from host alloc */ + scsi_host_put(shost); + return 0; +} + +EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session); + /* * iscsi interface functions */ @@ -572,13 +560,13 @@ mempool_zone_get_skb(struct mempool_zone *zone) } static int -iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) +iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb) { unsigned long flags; int rc; skb_get(skb); - rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT); + rc = netlink_unicast(nls, skb, daemon_pid, MSG_DONTWAIT); if (rc < 0) { mempool_free(skb, zone->pool); printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc); @@ -586,7 +574,6 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) } spin_lock_irqsave(&zone->freelock, flags); - INIT_LIST_HEAD(skb_to_lh(skb)); list_add(skb_to_lh(skb), &zone->freequeue); spin_unlock_irqrestore(&zone->freelock, flags); @@ -600,14 +587,9 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, struct sk_buff *skb; struct iscsi_uevent *ev; char *pdu; - struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + data_size); - priv = iscsi_if_transport_lookup(conn->transport); - if (!priv) - return -EINVAL; - mempool_zone_complete(conn->z_pdu); skb = mempool_zone_get_skb(conn->z_pdu); @@ -618,20 +600,19 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, return -ENOMEM; } - nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); + nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); ev = NLMSG_DATA(nlh); memset(ev, 0, sizeof(*ev)); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_RECV_PDU; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) ev->iferror = -ENOMEM; - ev->r.recv_req.cid = conn->cid; - ev->r.recv_req.sid = iscsi_conn_get_sid(conn); + ev->r.recv_req.conn_handle = iscsi_handle(conn); pdu = (char*)ev + sizeof(*ev); memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); - return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid); + return iscsi_unicast_skb(conn->z_pdu, skb); } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); @@ -640,13 +621,8 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; - struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev)); - priv = iscsi_if_transport_lookup(conn->transport); - if (!priv) - return; - mempool_zone_complete(conn->z_error); skb = mempool_zone_get_skb(conn->z_error); @@ -656,17 +632,16 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) return; } - nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); + nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); ev = NLMSG_DATA(nlh); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_CONN_ERROR; if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) ev->iferror = -ENOMEM; ev->r.connerror.error = error; - ev->r.connerror.cid = conn->cid; - ev->r.connerror.sid = iscsi_conn_get_sid(conn); + ev->r.connerror.conn_handle = iscsi_handle(conn); - iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid); + iscsi_unicast_skb(conn->z_error, skb); dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", error); @@ -696,7 +671,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); nlh->nlmsg_flags = flags; memcpy(NLMSG_DATA(nlh), payload, size); - return iscsi_unicast_skb(z_reply, skb, pid); + return iscsi_unicast_skb(z_reply, skb); } static int @@ -708,18 +683,13 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) struct iscsi_cls_conn *conn; struct nlmsghdr *nlhstat; struct iscsi_uevent *evstat; - struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_stats) + sizeof(struct iscsi_stats_custom) * ISCSI_STATS_CUSTOM_MAX); int err = 0; - priv = iscsi_if_transport_lookup(transport); - if (!priv) - return -EINVAL; - - conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid); + conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle); if (!conn) return -EEXIST; @@ -735,7 +705,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) return -ENOMEM; } - nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0, + nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, (len - sizeof(*nlhstat)), 0); evstat = NLMSG_DATA(nlhstat); memset(evstat, 0, sizeof(*evstat)); @@ -743,10 +713,8 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) evstat->type = nlh->nlmsg_type; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) evstat->iferror = -ENOMEM; - evstat->u.get_stats.cid = - ev->u.get_stats.cid; - evstat->u.get_stats.sid = - ev->u.get_stats.sid; + evstat->u.get_stats.conn_handle = + ev->u.get_stats.conn_handle; stats = (struct iscsi_stats *) ((char*)evstat + sizeof(*evstat)); memset(stats, 0, sizeof(*stats)); @@ -761,7 +729,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) skb_trim(skbstat, NLMSG_ALIGN(actual_size)); nlhstat->nlmsg_len = actual_size; - err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid); + err = iscsi_unicast_skb(conn->z_pdu, skbstat); } while (err < 0 && err != -ECONNREFUSED); return err; @@ -772,21 +740,16 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) { struct iscsi_transport *transport = priv->iscsi_transport; struct iscsi_cls_session *session; - unsigned long flags; - uint32_t hostno; + uint32_t sid; - session = transport->create_session(transport, &priv->t, + session = transport->create_session(&priv->t, ev->u.c_session.initial_cmdsn, - &hostno); + &sid); if (!session) return -ENOMEM; - spin_lock_irqsave(&sesslock, flags); - list_add(&session->sess_list, &sesslist); - spin_unlock_irqrestore(&sesslock, flags); - - ev->r.c_session_ret.host_no = hostno; - ev->r.c_session_ret.sid = session->sid; + ev->r.c_session_ret.session_handle = iscsi_handle(session); + ev->r.c_session_ret.sid = sid; return 0; } @@ -797,20 +760,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) struct iscsi_cls_session *session; unsigned long flags; - session = iscsi_session_lookup(ev->u.c_conn.sid); - if (!session) { - printk(KERN_ERR "iscsi: invalid session %d\n", - ev->u.c_conn.sid); + session = iscsi_session_lookup(ev->u.c_conn.session_handle); + if (!session) return -EINVAL; - } conn = transport->create_conn(session, ev->u.c_conn.cid); - if (!conn) { - printk(KERN_ERR "iscsi: couldn't create a new " - "connection for session %d\n", - session->sid); + if (!conn) return -ENOMEM; - } conn->z_pdu = mempool_zone_init(Z_MAX_PDU, NLMSG_SPACE(sizeof(struct iscsi_uevent) + @@ -832,8 +788,7 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) goto free_pdu_pool; } - ev->r.c_conn_ret.sid = session->sid; - ev->r.c_conn_ret.cid = conn->cid; + ev->r.handle = iscsi_handle(conn); spin_lock_irqsave(&connlock, flags); list_add(&conn->conn_list, &connlist); @@ -857,7 +812,7 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev struct iscsi_cls_conn *conn; struct mempool_zone *z_error, *z_pdu; - conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); + conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle); if (!conn) return -EINVAL; spin_lock_irqsave(&connlock, flags); @@ -877,106 +832,6 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev return 0; } -static void -iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data) -{ - if (ev->u.set_param.len != sizeof(uint32_t)) - BUG(); - memcpy(value, data, min_t(uint32_t, sizeof(uint32_t), - ev->u.set_param.len)); -} - -static int -iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) -{ - char *data = (char*)ev + sizeof(*ev); - struct iscsi_cls_conn *conn; - struct iscsi_cls_session *session; - int err = 0; - uint32_t value = 0; - - session = iscsi_session_lookup(ev->u.set_param.sid); - conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); - if (!conn || !session) - return -EINVAL; - - switch (ev->u.set_param.param) { - case ISCSI_PARAM_SESS_RECOVERY_TMO: - iscsi_copy_param(ev, &value, data); - if (value != 0) - session->recovery_tmo = value; - break; - case ISCSI_PARAM_TARGET_NAME: - /* this should not change between logins */ - if (session->targetname) - return 0; - - session->targetname = kstrdup(data, GFP_KERNEL); - if (!session->targetname) - return -ENOMEM; - break; - case ISCSI_PARAM_TPGT: - iscsi_copy_param(ev, &value, data); - session->tpgt = value; - break; - case ISCSI_PARAM_PERSISTENT_PORT: - iscsi_copy_param(ev, &value, data); - conn->persistent_port = value; - break; - case ISCSI_PARAM_PERSISTENT_ADDRESS: - /* - * this is the address returned in discovery so it should - * not change between logins. - */ - if (conn->persistent_address) - return 0; - - conn->persistent_address = kstrdup(data, GFP_KERNEL); - if (!conn->persistent_address) - return -ENOMEM; - break; - default: - iscsi_copy_param(ev, &value, data); - err = transport->set_param(conn, ev->u.set_param.param, value); - } - - return err; -} - -static int -iscsi_if_transport_ep(struct iscsi_transport *transport, - struct iscsi_uevent *ev, int msg_type) -{ - struct sockaddr *dst_addr; - int rc = 0; - - switch (msg_type) { - case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: - if (!transport->ep_connect) - return -EINVAL; - - dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); - rc = transport->ep_connect(dst_addr, - ev->u.ep_connect.non_blocking, - &ev->r.ep_connect_ret.handle); - break; - case ISCSI_UEVENT_TRANSPORT_EP_POLL: - if (!transport->ep_poll) - return -EINVAL; - - ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle, - ev->u.ep_poll.timeout_ms); - break; - case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: - if (!transport->ep_disconnect) - return -EINVAL; - - transport->ep_disconnect(ev->u.ep_disconnect.ep_handle); - break; - } - return rc; -} - static int iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { @@ -986,7 +841,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct iscsi_internal *priv; struct iscsi_cls_session *session; struct iscsi_cls_conn *conn; - unsigned long flags; priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle)); if (!priv) @@ -996,21 +850,15 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (!try_module_get(transport->owner)) return -EINVAL; - priv->daemon_pid = NETLINK_CREDS(skb)->pid; - switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ev); break; case ISCSI_UEVENT_DESTROY_SESSION: - session = iscsi_session_lookup(ev->u.d_session.sid); - if (session) { - spin_lock_irqsave(&sesslock, flags); - list_del(&session->sess_list); - spin_unlock_irqrestore(&sesslock, flags); - + session = iscsi_session_lookup(ev->u.d_session.session_handle); + if (session) transport->destroy_session(session); - } else + else err = -EINVAL; break; case ISCSI_UEVENT_CREATE_CONN: @@ -1020,35 +868,41 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = iscsi_if_destroy_conn(transport, ev); break; case ISCSI_UEVENT_BIND_CONN: - session = iscsi_session_lookup(ev->u.b_conn.sid); - conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); + session = iscsi_session_lookup(ev->u.b_conn.session_handle); + conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle); if (session && conn) ev->r.retcode = transport->bind_conn(session, conn, - ev->u.b_conn.transport_eph, + ev->u.b_conn.transport_fd, ev->u.b_conn.is_leading); else err = -EINVAL; break; case ISCSI_UEVENT_SET_PARAM: - err = iscsi_set_param(transport, ev); + conn = iscsi_conn_lookup(ev->u.set_param.conn_handle); + if (conn) + ev->r.retcode = transport->set_param(conn, + ev->u.set_param.param, ev->u.set_param.value); + else + err = -EINVAL; break; case ISCSI_UEVENT_START_CONN: - conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); + conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle); if (conn) ev->r.retcode = transport->start_conn(conn); else err = -EINVAL; + break; case ISCSI_UEVENT_STOP_CONN: - conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); + conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle); if (conn) transport->stop_conn(conn, ev->u.stop_conn.flag); else err = -EINVAL; break; case ISCSI_UEVENT_SEND_PDU: - conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid); + conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle); if (conn) ev->r.retcode = transport->send_pdu(conn, (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), @@ -1060,11 +914,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case ISCSI_UEVENT_GET_STATS: err = iscsi_if_get_stats(transport, nlh); break; - case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: - case ISCSI_UEVENT_TRANSPORT_EP_POLL: - case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: - err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); - break; default: err = -EINVAL; break; @@ -1074,11 +923,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return err; } -/* - * Get message from skb (based on rtnetlink_rcv_skb). Each message is - * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or - * invalid creds are discarded silently. - */ +/* Get message from skb (based on rtnetlink_rcv_skb). Each message is + * processed by iscsi_if_recv_msg. Malformed skbs with wrong length are + * or invalid creds discarded silently. */ static void iscsi_if_rx(struct sock *sk, int len) { @@ -1090,6 +937,7 @@ iscsi_if_rx(struct sock *sk, int len) skb_pull(skb, skb->len); goto free_skb; } + daemon_pid = NETLINK_CREDS(skb)->pid; while (skb->len >= NLMSG_SPACE(0)) { int err; @@ -1140,10 +988,6 @@ free_skb: #define iscsi_cdev_to_conn(_cdev) \ iscsi_dev_to_conn(_cdev->dev) -#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \ -struct class_device_attribute class_device_attr_##_prefix##_##_name = \ - __ATTR(_name,_mode,_show,_store) - /* * iSCSI connection attrs */ @@ -1161,8 +1005,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \ #define iscsi_conn_int_attr(field, param, format) \ iscsi_conn_int_attr_show(param, format) \ -static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \ - NULL); +static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL); iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u"); iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u"); @@ -1170,26 +1013,6 @@ iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d"); iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); -iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d"); -iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d"); -iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u"); - -#define iscsi_conn_str_attr_show(param) \ -static ssize_t \ -show_conn_str_param_##param(struct class_device *cdev, char *buf) \ -{ \ - struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ - struct iscsi_transport *t = conn->transport; \ - return t->get_conn_str_param(conn, param, buf); \ -} - -#define iscsi_conn_str_attr(field, param) \ - iscsi_conn_str_attr_show(param) \ -static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \ - NULL); - -iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); -iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS); #define iscsi_cdev_to_session(_cdev) \ iscsi_dev_to_session(_cdev->dev) @@ -1211,8 +1034,7 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \ #define iscsi_session_int_attr(field, param, format) \ iscsi_session_int_attr_show(param, format) \ -static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \ - NULL); +static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL); iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d"); iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu"); @@ -1222,89 +1044,18 @@ iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u"); iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d"); iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d"); iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); -iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d"); - -#define iscsi_session_str_attr_show(param) \ -static ssize_t \ -show_session_str_param_##param(struct class_device *cdev, char *buf) \ -{ \ - struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ - struct iscsi_transport *t = session->transport; \ - return t->get_session_str_param(session, param, buf); \ -} - -#define iscsi_session_str_attr(field, param) \ - iscsi_session_str_attr_show(param) \ -static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \ - NULL); - -iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME); - -/* - * Private session and conn attrs. userspace uses several iscsi values - * to identify each session between reboots. Some of these values may not - * be present in the iscsi_transport/LLD driver becuase userspace handles - * login (and failback for login redirect) so for these type of drivers - * the class manages the attrs and values for the iscsi_transport/LLD - */ -#define iscsi_priv_session_attr_show(field, format) \ -static ssize_t \ -show_priv_session_##field(struct class_device *cdev, char *buf) \ -{ \ - struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ - return sprintf(buf, format"\n", session->field); \ -} - -#define iscsi_priv_session_attr(field, format) \ - iscsi_priv_session_attr_show(field, format) \ -static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ - NULL) -iscsi_priv_session_attr(targetname, "%s"); -iscsi_priv_session_attr(tpgt, "%d"); -iscsi_priv_session_attr(recovery_tmo, "%d"); - -#define iscsi_priv_conn_attr_show(field, format) \ -static ssize_t \ -show_priv_conn_##field(struct class_device *cdev, char *buf) \ -{ \ - struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ - return sprintf(buf, format"\n", conn->field); \ -} -#define iscsi_priv_conn_attr(field, format) \ - iscsi_priv_conn_attr_show(field, format) \ -static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \ - NULL) -iscsi_priv_conn_attr(persistent_address, "%s"); -iscsi_priv_conn_attr(persistent_port, "%d"); - -#define SETUP_PRIV_SESSION_RD_ATTR(field) \ -do { \ - priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ - count++; \ -} while (0) - -#define SETUP_SESSION_RD_ATTR(field, param_flag) \ -do { \ - if (tt->param_mask & param_flag) { \ - priv->session_attrs[count] = &class_device_attr_sess_##field; \ +#define SETUP_SESSION_RD_ATTR(field, param) \ + if (priv->param_mask & (1 << param)) { \ + priv->session_attrs[count] = &class_device_attr_##field;\ count++; \ - } \ -} while (0) - -#define SETUP_PRIV_CONN_RD_ATTR(field) \ -do { \ - priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \ - count++; \ -} while (0) - -#define SETUP_CONN_RD_ATTR(field, param_flag) \ -do { \ - if (tt->param_mask & param_flag) { \ - priv->conn_attrs[count] = &class_device_attr_conn_##field; \ + } + +#define SETUP_CONN_RD_ATTR(field, param) \ + if (priv->param_mask & (1 << param)) { \ + priv->conn_attrs[count] = &class_device_attr_##field; \ count++; \ - } \ -} while (0) + } static int iscsi_session_match(struct attribute_container *cont, struct device *dev) @@ -1353,24 +1104,6 @@ static int iscsi_conn_match(struct attribute_container *cont, return &priv->conn_cont.ac == cont; } -static int iscsi_host_match(struct attribute_container *cont, - struct device *dev) -{ - struct Scsi_Host *shost; - struct iscsi_internal *priv; - - if (!scsi_is_host_device(dev)) - return 0; - - shost = dev_to_shost(dev); - if (!shost->transportt || - shost->transportt->host_attrs.ac.class != &iscsi_host_class.class) - return 0; - - priv = to_iscsi_internal(shost->transportt); - return &priv->t.host_attrs.ac == cont; -} - struct scsi_transport_template * iscsi_register_transport(struct iscsi_transport *tt) { @@ -1389,7 +1122,6 @@ iscsi_register_transport(struct iscsi_transport *tt) return NULL; INIT_LIST_HEAD(&priv->list); priv->iscsi_transport = tt; - priv->t.user_scan = iscsi_user_scan; priv->cdev.class = &iscsi_transport_class; snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name); @@ -1401,13 +1133,18 @@ iscsi_register_transport(struct iscsi_transport *tt) if (err) goto unregister_cdev; - /* host parameters */ - priv->t.host_attrs.ac.attrs = &priv->host_attrs[0]; - priv->t.host_attrs.ac.class = &iscsi_host_class.class; - priv->t.host_attrs.ac.match = iscsi_host_match; - priv->t.host_size = sizeof(struct iscsi_host); - priv->host_attrs[0] = NULL; - transport_container_register(&priv->t.host_attrs); + /* setup parameters mask */ + priv->param_mask = 0xFFFFFFFF; + if (!(tt->caps & CAP_MULTI_R2T)) + priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T); + if (!(tt->caps & CAP_HDRDGST)) + priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN); + if (!(tt->caps & CAP_DATADGST)) + priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN); + if (!(tt->caps & CAP_MARKERS)) { + priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN); + priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN); + } /* connection parameters */ priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; @@ -1415,25 +1152,12 @@ iscsi_register_transport(struct iscsi_transport *tt) priv->conn_cont.ac.match = iscsi_conn_match; transport_container_register(&priv->conn_cont); - SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH); - SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH); - SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN); - SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN); - SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN); - SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN); - SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); - SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); - SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); - - if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS) - SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); - else - SETUP_PRIV_CONN_RD_ATTR(persistent_address); - - if (tt->param_mask & ISCSI_PERSISTENT_PORT) - SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); - else - SETUP_PRIV_CONN_RD_ATTR(persistent_port); + SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH); + SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH); + SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN); + SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN); + SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN); + SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN); BUG_ON(count > ISCSI_CONN_ATTRS); priv->conn_attrs[count] = NULL; @@ -1445,25 +1169,14 @@ iscsi_register_transport(struct iscsi_transport *tt) priv->session_cont.ac.match = iscsi_session_match; transport_container_register(&priv->session_cont); - SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN); - SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T); - SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN); - SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST); - SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST); - SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); - SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); - SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); - SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); - - if (tt->param_mask & ISCSI_TARGET_NAME) - SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); - else - SETUP_PRIV_SESSION_RD_ATTR(targetname); - - if (tt->param_mask & ISCSI_TPGT) - SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT); - else - SETUP_PRIV_SESSION_RD_ATTR(tpgt); + SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN); + SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T); + SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN); + SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST); + SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST); + SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN); + SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN) + SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL); BUG_ON(count > ISCSI_SESSION_ATTRS); priv->session_attrs[count] = NULL; @@ -1501,7 +1214,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) transport_container_unregister(&priv->conn_cont); transport_container_unregister(&priv->session_cont); - transport_container_unregister(&priv->t.host_attrs); sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); class_device_unregister(&priv->cdev); @@ -1545,13 +1257,9 @@ static __init int iscsi_transport_init(void) if (err) return err; - err = transport_class_register(&iscsi_host_class); - if (err) - goto unregister_transport_class; - err = transport_class_register(&iscsi_connection_class); if (err) - goto unregister_host_class; + goto unregister_transport_class; err = transport_class_register(&iscsi_session_class); if (err) @@ -1580,8 +1288,6 @@ unregister_session_class: transport_class_unregister(&iscsi_session_class); unregister_conn_class: transport_class_unregister(&iscsi_connection_class); -unregister_host_class: - transport_class_unregister(&iscsi_host_class); unregister_transport_class: class_unregister(&iscsi_transport_class); return err; @@ -1594,7 +1300,6 @@ static void __exit iscsi_transport_exit(void) netlink_unregister_notifier(&iscsi_nl_notifier); transport_class_unregister(&iscsi_connection_class); transport_class_unregister(&iscsi_session_class); - transport_class_unregister(&iscsi_host_class); class_unregister(&iscsi_transport_class); } diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index fbb53adee..968597781 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -7,6 +7,9 @@ * * Copyright (C) 2001 Russell King. * + * 2005/09/16: Enabled higher baud rates for 16C95x. + * (Mathias Adam ) + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -1745,6 +1748,14 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int else if ((port->flags & UPF_MAGIC_MULTIPLIER) && baud == (port->uartclk/8)) quot = 0x8002; + /* + * For 16C950s UART_TCR is used in combination with divisor==1 + * to achieve baud rates up to baud_base*4. + */ + else if ((port->type == PORT_16C950) && + baud > (port->uartclk/16)) + quot = 1; + else quot = uart_get_divisor(port, baud); @@ -1758,7 +1769,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; unsigned long flags; - unsigned int baud, quot; + unsigned int baud, quot, max_baud; switch (termios->c_cflag & CSIZE) { case CS5: @@ -1790,7 +1801,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, /* * Ask the core to calculate the divisor for us. */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + max_baud = (up->port.type == PORT_16C950 ? port->uartclk/4 : port->uartclk/16); + baud = uart_get_baud_rate(port, termios, old, 0, max_baud); quot = serial8250_get_divisor(port, baud); /* @@ -1826,6 +1838,19 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, */ spin_lock_irqsave(&up->port.lock, flags); + /* + * 16C950 supports additional prescaler ratios between 1:16 and 1:4 + * thus increasing max baud rate to uartclk/4. + */ + if (up->port.type == PORT_16C950) { + if (baud == port->uartclk/4) + serial_icr_write(up, UART_TCR, 0x4); + else if (baud == port->uartclk/8) + serial_icr_write(up, UART_TCR, 0x8); + else + serial_icr_write(up, UART_TCR, 0); + } + /* * Update the per-port timeout. */ @@ -2243,10 +2268,14 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) touch_nmi_watchdog(); - if (oops_in_progress) { - locked = spin_trylock_irqsave(&up->port.lock, flags); + local_irq_save(flags); + if (up->port.sysrq) { + /* serial8250_handle_port() already took the lock */ + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); } else - spin_lock_irqsave(&up->port.lock, flags); + spin_lock(&up->port.lock); /* * First save the IER then disable the interrupts @@ -2268,7 +2297,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) serial_out(up, UART_IER, ier); if (locked) - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock(&up->port.lock); + local_irq_restore(flags); } static int serial8250_console_setup(struct console *co, char *options) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7d22dc047..d2716173d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -11,6 +11,7 @@ menu "Serial drivers" config SERIAL_8250 tristate "8250/16550 and compatible serial support" depends on (BROKEN || !SPARC) + depends on !XEN_DISABLE_SERIAL select SERIAL_CORE ---help--- This selects whether you want to include the driver for the standard @@ -803,6 +804,7 @@ config SERIAL_MPC52xx tristate "Freescale MPC52xx family PSC serial support" depends on PPC_MPC52xx select SERIAL_CORE + select FW_LOADER help This drivers support the MPC52xx PSC serial ports. If you would like to use them, you must answer Y or M to this option. Not that diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 7abe532d7..17839e753 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1968,16 +1968,16 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) struct termios termios; /* - * Get the termios for this line + * First try to use the console cflag setting. */ - tty_get_termios(drv->tty_driver, port->line, &termios); + memset(&termios, 0, sizeof(struct termios)); + termios.c_cflag = port->cons->cflag; /* - * If the console cflag is still set, subsitute that - * for the termios cflag. + * If that's unset, use the tty termios setting. */ - if (port->cons->cflag) - termios.c_cflag = port->cons->cflag; + if (state->info && state->info->tty && termios.c_cflag == 0) + termios = *state->info->tty->termios; port->ops->set_termios(port, &termios, NULL); console_start(port->cons); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index a06d84c19..5f44354c4 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -264,7 +264,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) * need to change any toggles in this URB */ td = list_entry(urbp->td_list.next, struct uhci_td, list); if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) { - td = list_entry(urbp->td_list.next, struct uhci_td, + td = list_entry(urbp->td_list.prev, struct uhci_td, list); toggle = uhci_toggle(td_token(td)) ^ 1; @@ -896,12 +896,14 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) /* * This URB stopped short of its end. We have to * fix up the toggles of the following URBs on the - * queue and restart the queue. + * queue and restart the queue. But only if this + * TD isn't the last one in the URB. * * Do this only the first time we encounter the * short URB. */ - if (!urbp->short_transfer) { + if (!urbp->short_transfer && + &td->list != urbp->td_list.prev) { urbp->short_transfer = 1; urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^ 1; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 986d76222..ad9ddecf1 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -553,6 +553,10 @@ struct ftdi_private { int force_baud; /* if non-zero, force the baud rate to this value */ int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ + + spinlock_t tx_lock; /* spinlock for transmit state */ + unsigned long tx_outstanding_bytes; + unsigned long tx_outstanding_urbs; }; /* Used for TIOCMIWAIT */ @@ -626,6 +630,9 @@ static struct usb_serial_driver ftdi_sio_device = { #define HIGH 1 #define LOW 0 +/* number of outstanding urbs to prevent userspace DoS from happening */ +#define URB_UPPER_LIMIT 42 + /* * *************************************************************************** * Utlity functions @@ -1156,6 +1163,7 @@ static int ftdi_sio_attach (struct usb_serial *serial) } spin_lock_init(&priv->rx_lock); + spin_lock_init(&priv->tx_lock); init_waitqueue_head(&priv->delta_msr_wait); /* This will push the characters through immediately rather than queue a task to deliver them */ @@ -1372,6 +1380,7 @@ static int ftdi_write (struct usb_serial_port *port, int data_offset ; /* will be 1 for the SIO and 0 otherwise */ int status; int transfer_size; + unsigned long flags; dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); @@ -1379,6 +1388,13 @@ static int ftdi_write (struct usb_serial_port *port, dbg("write request of 0 bytes"); return 0; } + spin_lock_irqsave(&priv->tx_lock, flags); + if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { + spin_unlock_irqrestore(&priv->tx_lock, flags); + dbg("%s - write limit hit\n", __FUNCTION__); + return 0; + } + spin_unlock_irqrestore(&priv->tx_lock, flags); data_offset = priv->write_offset; dbg("data_offset set to %d",data_offset); @@ -1445,6 +1461,11 @@ static int ftdi_write (struct usb_serial_port *port, err("%s - failed submitting write urb, error %d", __FUNCTION__, status); count = status; kfree (buffer); + } else { + spin_lock_irqsave(&priv->tx_lock, flags); + ++priv->tx_outstanding_urbs; + priv->tx_outstanding_bytes += count; + spin_unlock_irqrestore(&priv->tx_lock, flags); } /* we are done with this urb, so let the host driver @@ -1460,7 +1481,11 @@ static int ftdi_write (struct usb_serial_port *port, static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) { + unsigned long flags; struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct ftdi_private *priv; + int data_offset; /* will be 1 for the SIO and 0 otherwise */ + unsigned long countback; /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree (urb->transfer_buffer); @@ -1472,34 +1497,67 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) return; } + priv = usb_get_serial_port_data(port); + if (!priv) { + dbg("%s - bad port private data pointer - exiting", __FUNCTION__); + return; + } + /* account for transferred data */ + countback = urb->actual_length; + data_offset = priv->write_offset; + if (data_offset > 0) { + /* Subtract the control bytes */ + countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ)); + } + spin_lock_irqsave(&priv->tx_lock, flags); + --priv->tx_outstanding_urbs; + priv->tx_outstanding_bytes -= countback; + spin_unlock_irqrestore(&priv->tx_lock, flags); + schedule_work(&port->work); } /* ftdi_write_bulk_callback */ static int ftdi_write_room( struct usb_serial_port *port ) { + struct ftdi_private *priv = usb_get_serial_port_data(port); + int room; + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); - /* - * We really can take anything the user throws at us - * but let's pick a nice big number to tell the tty - * layer that we have lots of free space - */ - return 2048; + spin_lock_irqsave(&priv->tx_lock, flags); + if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) { + /* + * We really can take anything the user throws at us + * but let's pick a nice big number to tell the tty + * layer that we have lots of free space + */ + room = 2048; + } else { + room = 0; + } + spin_unlock_irqrestore(&priv->tx_lock, flags); + return room; } /* ftdi_write_room */ static int ftdi_chars_in_buffer (struct usb_serial_port *port) { /* ftdi_chars_in_buffer */ + struct ftdi_private *priv = usb_get_serial_port_data(port); + int buffered; + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); - /* - * We can't really account for how much data we - * have sent out, but hasn't made it through to the - * device, so just tell the tty layer that everything - * is flushed. - */ - return 0; + spin_lock_irqsave(&priv->tx_lock, flags); + buffered = (int)priv->tx_outstanding_bytes; + spin_unlock_irqrestore(&priv->tx_lock, flags); + if (buffered < 0) { + err("%s outstanding tx bytes is negative!", __FUNCTION__); + buffered = 0; + } + return buffered; } /* ftdi_chars_in_buffer */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 2de6528aa..a1a83029c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -113,6 +113,12 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Orgad Shaneh */ +UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100, + "Samsung", "MP3 Player", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE), + /* Reported by Christian Leber */ UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100, "TrekStor", @@ -133,12 +139,6 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Pete Zaitcev , bz#176584 */ -UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, - "GENERIC", "MP3 PLAYER", /* MyMusix PD-205 on the outside. */ - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_RESIDUE ), - /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index dd1086343..0142fe82f 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -593,6 +593,15 @@ static int get_transport(struct us_data *us) break; #endif +#ifdef CONFIG_USB_STORAGE_ALAUDA + case US_PR_ALAUDA: + us->transport_name = "Alauda Control/Bulk"; + us->transport = alauda_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + break; +#endif + default: return -EIO; } @@ -648,15 +657,6 @@ static int get_protocol(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - default: return -EIO; } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4587087d7..2fd9ab7f4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -513,7 +513,7 @@ config FB_HGA_ACCEL config VIDEO_SELECT bool - depends on (FB = y) && X86 + depends on (FB = y) && X86 && !XEN default y config FB_SGIVW diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c index 0a2ed2fd3..2ade75291 100644 --- a/drivers/video/console/softcursor.c +++ b/drivers/video/console/softcursor.c @@ -27,7 +27,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) struct fb_image *image; u8 *dst; static u8 *src=NULL; - static int allocsize=0; + static int allocsize = 0; if (info->state != FBINFO_STATE_RUNNING) return 0; @@ -41,8 +41,10 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) allocsize = dsize + sizeof(struct fb_image); src = kmalloc(allocsize, GFP_ATOMIC); - if (!src) + if (!src) { + allocsize = 0; return -ENOMEM; + } } image = (struct fb_image *) (src + dsize); diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 7bb479830..79eddeec1 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -1,13 +1,17 @@ - - +obj-y += core/ obj-y += console/ obj-y += evtchn/ -obj-y += balloon/ +obj-y += privcmd/ +obj-y += xenbus/ -obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += privcmd/ +obj-$(CONFIG_XEN_UTIL) += util.o +obj-$(CONFIG_XEN_BALLOON) += balloon/ +obj-$(CONFIG_XEN_DEVMEM) += char/ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/ +obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/ obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ +obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/ obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/ -obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/ - +obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/ +obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/ diff --git a/drivers/xen/balloon/balloon.c b/drivers/xen/balloon/balloon.c index 649f64c40..322675334 100644 --- a/drivers/xen/balloon/balloon.c +++ b/drivers/xen/balloon/balloon.c @@ -5,9 +5,13 @@ * * Copyright (c) 2003, B Dragovic * Copyright (c) 2003-2004, M Williamson, K Fraser + * Copyright (c) 2005 Dan M. Smith, IBM Corporation * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without @@ -40,25 +44,43 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include #include #include +#include + +#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) + +#ifdef CONFIG_PROC_FS static struct proc_dir_entry *balloon_pde; +#endif static DECLARE_MUTEX(balloon_mutex); -spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED; + +/* + * Protects atomic reservation decrease/increase against concurrent increases. + * Also protects non-atomic updates of current_pages and driver_pages, and + * balloon lists. + */ +DEFINE_SPINLOCK(balloon_lock); /* We aim for 'current allocation' == 'target allocation'. */ static unsigned long current_pages; static unsigned long target_pages; +/* We increase/decrease in batches which fit in a page */ +static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; + +/* VM /proc information for memory */ +extern unsigned long totalram_pages; + /* We may hit the hard limit in Xen. If we do then we remember it. */ static unsigned long hard_limit; @@ -77,79 +99,230 @@ static void balloon_process(void *unused); static DECLARE_WORK(balloon_worker, balloon_process, NULL); static struct timer_list balloon_timer; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -/* Use the private and mapping fields of struct page as a list. */ -#define PAGE_TO_LIST(p) ( (struct list_head *)&p->private ) -#define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l), \ - struct page, private ) ) -#define UNLIST_PAGE(p) do { list_del(PAGE_TO_LIST(p)); \ - p->mapping = NULL; \ - p->private = 0; } while(0) -#else -/* There's a dedicated list field in struct page we can use. */ -#define PAGE_TO_LIST(p) ( &p->list ) -#define LIST_TO_PAGE(l) ( list_entry(l, struct page, list) ) -#define UNLIST_PAGE(p) ( list_del(&p->list) ) -#define pte_offset_kernel pte_offset -#define pud_t pgd_t -#define pud_offset(d, va) d -#define pud_none(d) 0 -#define pud_bad(d) 0 -#define subsys_initcall(_fn) __initcall(_fn) -#define pfn_to_page(_pfn) (mem_map + (_pfn)) -#endif +/* When ballooning out (allocating memory to return to Xen) we don't really + want the kernel to try too hard since that can trigger the oom killer. */ +#define GFP_BALLOON \ + (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) + +#define PAGE_TO_LIST(p) (&(p)->lru) +#define LIST_TO_PAGE(l) list_entry((l), struct page, lru) +#define UNLIST_PAGE(p) \ + do { \ + list_del(PAGE_TO_LIST(p)); \ + PAGE_TO_LIST(p)->next = NULL; \ + PAGE_TO_LIST(p)->prev = NULL; \ + } while(0) #define IPRINTK(fmt, args...) \ - printk(KERN_INFO "xen_mem: " fmt, ##args) + printk(KERN_INFO "xen_mem: " fmt, ##args) #define WPRINTK(fmt, args...) \ - printk(KERN_WARNING "xen_mem: " fmt, ##args) + printk(KERN_WARNING "xen_mem: " fmt, ##args) /* balloon_append: add the given page to the balloon. */ static void balloon_append(struct page *page) { - /* Low memory is re-populated first, so highmem pages go at list tail. */ - if ( PageHighMem(page) ) - { - list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); - balloon_high++; - } - else - { - list_add(PAGE_TO_LIST(page), &ballooned_pages); - balloon_low++; - } + /* Lowmem is re-populated first, so highmem pages go at list tail. */ + if (PageHighMem(page)) { + list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); + balloon_high++; + } else { + list_add(PAGE_TO_LIST(page), &ballooned_pages); + balloon_low++; + } } /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ static struct page *balloon_retrieve(void) { - struct page *page; + struct page *page; + + if (list_empty(&ballooned_pages)) + return NULL; + + page = LIST_TO_PAGE(ballooned_pages.next); + UNLIST_PAGE(page); - if ( list_empty(&ballooned_pages) ) - return NULL; + if (PageHighMem(page)) + balloon_high--; + else + balloon_low--; - page = LIST_TO_PAGE(ballooned_pages.next); - UNLIST_PAGE(page); + return page; +} - if ( PageHighMem(page) ) - balloon_high--; - else - balloon_low--; +static struct page *balloon_first_page(void) +{ + if (list_empty(&ballooned_pages)) + return NULL; + return LIST_TO_PAGE(ballooned_pages.next); +} - return page; +static struct page *balloon_next_page(struct page *page) +{ + struct list_head *next = PAGE_TO_LIST(page)->next; + if (next == &ballooned_pages) + return NULL; + return LIST_TO_PAGE(next); } static void balloon_alarm(unsigned long unused) { - schedule_work(&balloon_worker); + schedule_work(&balloon_worker); } static unsigned long current_target(void) { - unsigned long target = min(target_pages, hard_limit); - if ( target > (current_pages + balloon_low + balloon_high) ) - target = current_pages + balloon_low + balloon_high; - return target; + unsigned long target = min(target_pages, hard_limit); + if (target > (current_pages + balloon_low + balloon_high)) + target = current_pages + balloon_low + balloon_high; + return target; +} + +static int increase_reservation(unsigned long nr_pages) +{ + unsigned long pfn, i, flags; + struct page *page; + long rc; + struct xen_memory_reservation reservation = { + .address_bits = 0, + .extent_order = 0, + .domid = DOMID_SELF + }; + + if (nr_pages > ARRAY_SIZE(frame_list)) + nr_pages = ARRAY_SIZE(frame_list); + + balloon_lock(flags); + + page = balloon_first_page(); + for (i = 0; i < nr_pages; i++) { + BUG_ON(page == NULL); + frame_list[i] = page_to_pfn(page);; + page = balloon_next_page(page); + } + + set_xen_guest_handle(reservation.extent_start, frame_list); + reservation.nr_extents = nr_pages; + rc = HYPERVISOR_memory_op( + XENMEM_populate_physmap, &reservation); + if (rc < nr_pages) { + if (rc > 0) { + int ret; + + /* We hit the Xen hard limit: reprobe. */ + reservation.nr_extents = rc; + ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation); + BUG_ON(ret != rc); + } + if (rc >= 0) + hard_limit = current_pages + rc - driver_pages; + goto out; + } + + for (i = 0; i < nr_pages; i++) { + page = balloon_retrieve(); + BUG_ON(page == NULL); + + pfn = page_to_pfn(page); + BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) && + phys_to_machine_mapping_valid(pfn)); + + /* Update P->M and M->P tables. */ + set_phys_to_machine(pfn, frame_list[i]); + xen_machphys_update(frame_list[i], pfn); + + /* Link back into the page tables if not highmem. */ + if (pfn < max_low_pfn) { + int ret; + ret = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + pfn_pte_ma(frame_list[i], PAGE_KERNEL), + 0); + BUG_ON(ret); + } + + /* Relinquish the page back to the allocator. */ + ClearPageReserved(page); + init_page_count(page); + __free_page(page); + } + + current_pages += nr_pages; + totalram_pages = current_pages; + + out: + balloon_unlock(flags); + + return 0; +} + +static int decrease_reservation(unsigned long nr_pages) +{ + unsigned long pfn, i, flags; + struct page *page; + void *v; + int need_sleep = 0; + int ret; + struct xen_memory_reservation reservation = { + .address_bits = 0, + .extent_order = 0, + .domid = DOMID_SELF + }; + + if (nr_pages > ARRAY_SIZE(frame_list)) + nr_pages = ARRAY_SIZE(frame_list); + + for (i = 0; i < nr_pages; i++) { + if ((page = alloc_page(GFP_BALLOON)) == NULL) { + nr_pages = i; + need_sleep = 1; + break; + } + + pfn = page_to_pfn(page); + frame_list[i] = pfn_to_mfn(pfn); + + if (!PageHighMem(page)) { + v = phys_to_virt(pfn << PAGE_SHIFT); + scrub_pages(v, 1); + ret = HYPERVISOR_update_va_mapping( + (unsigned long)v, __pte_ma(0), 0); + BUG_ON(ret); + } +#ifdef CONFIG_XEN_SCRUB_PAGES + else { + v = kmap(page); + scrub_pages(v, 1); + kunmap(page); + } +#endif + } + + /* Ensure that ballooned highmem pages don't have kmaps. */ + kmap_flush_unused(); + flush_tlb_all(); + + balloon_lock(flags); + + /* No more mappings: invalidate P2M and add to balloon. */ + for (i = 0; i < nr_pages; i++) { + pfn = mfn_to_pfn(frame_list[i]); + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + balloon_append(pfn_to_page(pfn)); + } + + set_xen_guest_handle(reservation.extent_start, frame_list); + reservation.nr_extents = nr_pages; + ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); + BUG_ON(ret != nr_pages); + + current_pages -= nr_pages; + totalram_pages = current_pages; + + balloon_unlock(flags); + + return need_sleep; } /* @@ -160,279 +333,285 @@ static unsigned long current_target(void) */ static void balloon_process(void *unused) { - unsigned long *mfn_list, pfn, i, flags; - struct page *page; - long credit, debt, rc; - void *v; - - down(&balloon_mutex); - - retry: - mfn_list = NULL; - - if ( (credit = current_target() - current_pages) > 0 ) - { - mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list)); - if ( mfn_list == NULL ) - goto out; - - balloon_lock(flags); - rc = HYPERVISOR_dom_mem_op( - MEMOP_increase_reservation, mfn_list, credit, 0); - balloon_unlock(flags); - if ( rc < credit ) - { - /* We hit the Xen hard limit: reprobe. */ - if ( HYPERVISOR_dom_mem_op( - MEMOP_decrease_reservation, mfn_list, rc, 0) != rc ) - BUG(); - hard_limit = current_pages + rc - driver_pages; - vfree(mfn_list); - goto retry; - } - - for ( i = 0; i < credit; i++ ) - { - if ( (page = balloon_retrieve()) == NULL ) - BUG(); - - pfn = page - mem_map; - if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) - BUG(); - - /* Update P->M and M->P tables. */ - phys_to_machine_mapping[pfn] = mfn_list[i]; - xen_machphys_update(mfn_list[i], pfn); - - /* Link back into the page tables if it's not a highmem page. */ - if ( pfn < max_low_pfn ) - { - HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - __pte_ma((mfn_list[i] << PAGE_SHIFT) | - pgprot_val(PAGE_KERNEL)), - 0); - } - - /* Finally, relinquish the memory back to the system allocator. */ - ClearPageReserved(page); - set_page_count(page, 1); - __free_page(page); - } - - current_pages += credit; - } - else if ( credit < 0 ) - { - debt = -credit; - - mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list)); - if ( mfn_list == NULL ) - goto out; - - for ( i = 0; i < debt; i++ ) - { - if ( (page = alloc_page(GFP_HIGHUSER)) == NULL ) - { - debt = i; - break; - } - - pfn = page - mem_map; - mfn_list[i] = phys_to_machine_mapping[pfn]; - - if ( !PageHighMem(page) ) - { - v = phys_to_virt(pfn << PAGE_SHIFT); - scrub_pages(v, 1); - HYPERVISOR_update_va_mapping( - (unsigned long)v, __pte_ma(0), 0); - } -#ifdef CONFIG_XEN_SCRUB_PAGES - else - { - v = kmap(page); - scrub_pages(v, 1); - kunmap(page); - } -#endif - } + int need_sleep = 0; + long credit; - /* Ensure that ballooned highmem pages don't have cached mappings. */ - kmap_flush_unused(); - flush_tlb_all(); + down(&balloon_mutex); - /* No more mappings: invalidate pages in P2M and add to balloon. */ - for ( i = 0; i < debt; i++ ) - { - pfn = mfn_to_pfn(mfn_list[i]); - phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; - balloon_append(pfn_to_page(pfn)); - } + do { + credit = current_target() - current_pages; + if (credit > 0) + need_sleep = (increase_reservation(credit) != 0); + if (credit < 0) + need_sleep = (decrease_reservation(-credit) != 0); - if ( HYPERVISOR_dom_mem_op( - MEMOP_decrease_reservation, mfn_list, debt, 0) != debt ) - BUG(); - - current_pages -= debt; - } - - out: - if ( mfn_list != NULL ) - vfree(mfn_list); +#ifndef CONFIG_PREEMPT + if (need_resched()) + schedule(); +#endif + } while ((credit != 0) && !need_sleep); - /* Schedule more work if there is some still to be done. */ - if ( current_target() != current_pages ) - mod_timer(&balloon_timer, jiffies + HZ); + /* Schedule more work if there is some still to be done. */ + if (current_target() != current_pages) + mod_timer(&balloon_timer, jiffies + HZ); - up(&balloon_mutex); + up(&balloon_mutex); } /* Resets the Xen limit, sets new target, and kicks off processing. */ static void set_new_target(unsigned long target) { - /* No need for lock. Not read-modify-write updates. */ - hard_limit = ~0UL; - target_pages = target; - schedule_work(&balloon_worker); + /* No need for lock. Not read-modify-write updates. */ + hard_limit = ~0UL; + target_pages = target; + schedule_work(&balloon_worker); } -static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) +static struct xenbus_watch target_watch = { - switch ( msg->subtype ) - { - case CMSG_MEM_REQUEST_SET: - { - mem_request_t *req = (mem_request_t *)&msg->msg[0]; - set_new_target(req->target); - req->status = 0; - } - break; - - default: - msg->length = 0; - break; - } - - ctrl_if_send_response(msg); + .node = "memory/target" +}; + +/* React to a change in the target key */ +static void watch_target(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + unsigned long long new_target; + int err; + + err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target); + if (err != 1) { + /* This is ok (for domain0 at least) - so just return */ + return; + } + + /* The given memory/target value is in KiB, so it needs converting to + * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. + */ + set_new_target(new_target >> (PAGE_SHIFT - 10)); +} + +static int balloon_init_watcher(struct notifier_block *notifier, + unsigned long event, + void *data) +{ + int err; + + err = register_xenbus_watch(&target_watch); + if (err) + printk(KERN_ERR "Failed to set balloon watcher\n"); + + return NOTIFY_DONE; } +#ifdef CONFIG_PROC_FS static int balloon_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { - char memstring[64], *endchar; - unsigned long long target_bytes; + char memstring[64], *endchar; + unsigned long long target_bytes; - if ( !capable(CAP_SYS_ADMIN) ) - return -EPERM; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; - if ( count <= 1 ) - return -EBADMSG; /* runt */ - if ( count > sizeof(memstring) ) - return -EFBIG; /* too long */ + if (count <= 1) + return -EBADMSG; /* runt */ + if (count > sizeof(memstring)) + return -EFBIG; /* too long */ - if ( copy_from_user(memstring, buffer, count) ) - return -EFAULT; - memstring[sizeof(memstring)-1] = '\0'; + if (copy_from_user(memstring, buffer, count)) + return -EFAULT; + memstring[sizeof(memstring)-1] = '\0'; - target_bytes = memparse(memstring, &endchar); - set_new_target(target_bytes >> PAGE_SHIFT); + target_bytes = memparse(memstring, &endchar); + set_new_target(target_bytes >> PAGE_SHIFT); - return count; + return count; } static int balloon_read(char *page, char **start, off_t off, - int count, int *eof, void *data) + int count, int *eof, void *data) { - int len; - -#define K(_p) ((_p)<<(PAGE_SHIFT-10)) - len = sprintf( - page, - "Current allocation: %8lu kB\n" - "Requested target: %8lu kB\n" - "Low-mem balloon: %8lu kB\n" - "High-mem balloon: %8lu kB\n" - "Xen hard limit: ", - K(current_pages), K(target_pages), K(balloon_low), K(balloon_high)); - - if ( hard_limit != ~0UL ) - len += sprintf( - page + len, - "%8lu kB (inc. %8lu kB driver headroom)\n", - K(hard_limit), K(driver_pages)); - else - len += sprintf( - page + len, - " ??? kB\n"); - - *eof = 1; - return len; + int len; + + len = sprintf( + page, + "Current allocation: %8lu kB\n" + "Requested target: %8lu kB\n" + "Low-mem balloon: %8lu kB\n" + "High-mem balloon: %8lu kB\n" + "Xen hard limit: ", + PAGES2KB(current_pages), PAGES2KB(target_pages), + PAGES2KB(balloon_low), PAGES2KB(balloon_high)); + + if (hard_limit != ~0UL) { + len += sprintf( + page + len, + "%8lu kB (inc. %8lu kB driver headroom)\n", + PAGES2KB(hard_limit), PAGES2KB(driver_pages)); + } else { + len += sprintf( + page + len, + " ??? kB\n"); + } + + *eof = 1; + return len; } +#endif + +static struct notifier_block xenstore_notifier; static int __init balloon_init(void) { - unsigned long pfn; - struct page *page; + unsigned long pfn; + struct page *page; + + if (!is_running_on_xen()) + return -ENODEV; + + IPRINTK("Initialising balloon driver.\n"); + + current_pages = min(xen_start_info->nr_pages, max_pfn); + totalram_pages = current_pages; + target_pages = current_pages; + balloon_low = 0; + balloon_high = 0; + driver_pages = 0UL; + hard_limit = ~0UL; - IPRINTK("Initialising balloon driver.\n"); + init_timer(&balloon_timer); + balloon_timer.data = 0; + balloon_timer.function = balloon_alarm; + +#ifdef CONFIG_PROC_FS + if ((balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL) { + WPRINTK("Unable to create /proc/xen/balloon.\n"); + return -1; + } + + balloon_pde->read_proc = balloon_read; + balloon_pde->write_proc = balloon_write; +#endif + + /* Initialise the balloon with excess memory space. */ + for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) { + page = pfn_to_page(pfn); + if (!PageReserved(page)) + balloon_append(page); + } - current_pages = min(xen_start_info.nr_pages, max_pfn); - target_pages = current_pages; - balloon_low = 0; - balloon_high = 0; - driver_pages = 0UL; - hard_limit = ~0UL; + target_watch.callback = watch_target; + xenstore_notifier.notifier_call = balloon_init_watcher; - init_timer(&balloon_timer); - balloon_timer.data = 0; - balloon_timer.function = balloon_alarm; + register_xenstore_notifier(&xenstore_notifier); - if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL ) - { - WPRINTK("Unable to create /proc/xen/balloon.\n"); - return -1; - } - - balloon_pde->read_proc = balloon_read; - balloon_pde->write_proc = balloon_write; - - (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0); - - /* Initialise the balloon with excess memory space. */ - for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ ) - { - page = &mem_map[pfn]; - if ( !PageReserved(page) ) - balloon_append(page); - } - - return 0; + return 0; } subsys_initcall(balloon_init); void balloon_update_driver_allowance(long delta) { - unsigned long flags; - balloon_lock(flags); - driver_pages += delta; /* non-atomic update */ - balloon_unlock(flags); + unsigned long flags; + + balloon_lock(flags); + driver_pages += delta; + balloon_unlock(flags); } -void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) +static int dealloc_pte_fn( + pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { - unsigned long flags; + unsigned long mfn = pte_mfn(*pte); + int ret; + struct xen_memory_reservation reservation = { + .nr_extents = 1, + .extent_order = 0, + .domid = DOMID_SELF + }; + set_xen_guest_handle(reservation.extent_start, &mfn); + set_pte_at(&init_mm, addr, pte, __pte_ma(0)); + set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY); + ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); + BUG_ON(ret != 1); + return 0; +} - balloon_lock(flags); - if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, - mfn_list, nr_mfns, 0) != nr_mfns ) - BUG(); - current_pages -= nr_mfns; /* non-atomic update */ - balloon_unlock(flags); +struct page *balloon_alloc_empty_page_range(unsigned long nr_pages) +{ + unsigned long vstart, flags; + unsigned int order = get_order(nr_pages * PAGE_SIZE); + int ret; + unsigned long i; + struct page *page; + + vstart = __get_free_pages(GFP_KERNEL, order); + if (vstart == 0) + return NULL; + + scrub_pages(vstart, 1 << order); + + balloon_lock(flags); + if (xen_feature(XENFEAT_auto_translated_physmap)) { + unsigned long gmfn = __pa(vstart) >> PAGE_SHIFT; + struct xen_memory_reservation reservation = { + .nr_extents = 1, + .extent_order = order, + .domid = DOMID_SELF + }; + set_xen_guest_handle(reservation.extent_start, &gmfn); + ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation); + if (ret == -ENOSYS) + goto err; + BUG_ON(ret != 1); + } else { + ret = apply_to_page_range(&init_mm, vstart, PAGE_SIZE << order, + dealloc_pte_fn, NULL); + if (ret == -ENOSYS) + goto err; + BUG_ON(ret); + } + current_pages -= 1UL << order; + totalram_pages = current_pages; + balloon_unlock(flags); + + schedule_work(&balloon_worker); + + flush_tlb_all(); + + page = virt_to_page(vstart); + + for (i = 0; i < (1UL << order); i++) + init_page_count(page + i); + + return page; + + err: + free_pages(vstart, order); + balloon_unlock(flags); + return NULL; +} - schedule_work(&balloon_worker); +void balloon_dealloc_empty_page_range( + struct page *page, unsigned long nr_pages) +{ + unsigned long i, flags; + unsigned int order = get_order(nr_pages * PAGE_SIZE); + + balloon_lock(flags); + for (i = 0; i < (1UL << order); i++) { + BUG_ON(page_count(page + i) != 1); + balloon_append(page + i); + } + balloon_unlock(flags); + + schedule_work(&balloon_worker); } -EXPORT_SYMBOL(balloon_update_driver_allowance); -EXPORT_SYMBOL(balloon_put_pages); +EXPORT_SYMBOL_GPL(balloon_update_driver_allowance); +EXPORT_SYMBOL_GPL(balloon_alloc_empty_page_range); +EXPORT_SYMBOL_GPL(balloon_dealloc_empty_page_range); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/blkback/Makefile b/drivers/xen/blkback/Makefile index a27fe65f4..8bab63da3 100644 --- a/drivers/xen/blkback/Makefile +++ b/drivers/xen/blkback/Makefile @@ -1,2 +1,3 @@ +obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o -obj-y := blkback.o control.o interface.o vbd.o +blkbk-y := blkback.o xenbus.o interface.o vbd.o diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c index 2554f999d..c5b3eee0b 100644 --- a/drivers/xen/blkback/blkback.c +++ b/drivers/xen/blkback/blkback.c @@ -9,33 +9,60 @@ * * Copyright (c) 2003-2004, Keir Fraser & Steve Hand * Copyright (c) 2005, Christopher Clark + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ +#include +#include +#include +#include +#include #include "common.h" -#include -#ifdef CONFIG_XEN_BLKDEV_GRANT -#include -#endif /* * These are rather arbitrary. They are fairly large because adjacent requests * pulled from a communication ring are quite likely to end up being part of * the same scatter/gather request at the disc. * - * ** TRY INCREASING 'MAX_PENDING_REQS' IF WRITE SPEEDS SEEM TOO LOW ** + * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW ** + * * This will increase the chances of being able to write whole tracks. * 64 should be enough to keep us competitive with Linux. */ -#define MAX_PENDING_REQS 64 -#define BATCH_PER_DOMAIN 16 +static int blkif_reqs = 64; +module_param_named(reqs, blkif_reqs, int, 0); +MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate"); -static unsigned long mmap_vstart; -#define MMAP_PAGES \ - (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST) -#define MMAP_VADDR(_req,_seg) \ - (mmap_vstart + \ - ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \ - ((_seg) * PAGE_SIZE)) +static int mmap_pages; + +/* Run-time switchable: /sys/module/blkback/parameters/ */ +static unsigned int log_stats = 0; +static unsigned int debug_lvl = 0; +module_param(log_stats, int, 0644); +module_param(debug_lvl, int, 0644); /* * Each outstanding request that we've passed to the lower device layers has a @@ -44,223 +71,173 @@ static unsigned long mmap_vstart; * response queued for it, with the saved 'id' passed back. */ typedef struct { - blkif_t *blkif; - unsigned long id; - int nr_pages; - atomic_t pendcnt; - unsigned short operation; - int status; + blkif_t *blkif; + unsigned long id; + int nr_pages; + atomic_t pendcnt; + unsigned short operation; + int status; + struct list_head free_list; } pending_req_t; -/* - * We can't allocate pending_req's in order, since they may complete out of - * order. We therefore maintain an allocation ring. This ring also indicates - * when enough work has been passed down -- at that point the allocation ring - * will be empty. - */ -static pending_req_t pending_reqs[MAX_PENDING_REQS]; -static unsigned char pending_ring[MAX_PENDING_REQS]; -static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED; -/* NB. We use a different index type to differentiate from shared blk rings. */ -typedef unsigned int PEND_RING_IDX; -#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1)) -static PEND_RING_IDX pending_prod, pending_cons; -#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static kmem_cache_t *buffer_head_cachep; -#else -static request_queue_t *plugged_queue; -static inline void flush_plugged_queue(void) -{ - request_queue_t *q = plugged_queue; - if ( q != NULL ) - { - if ( q->unplug_fn != NULL ) - q->unplug_fn(q); - blk_put_queue(q); - plugged_queue = NULL; - } -} -#endif +static pending_req_t *pending_reqs; +static struct list_head pending_free; +static DEFINE_SPINLOCK(pending_free_lock); +static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq); -#ifdef CONFIG_XEN_BLKDEV_GRANT -/* When using grant tables to map a frame for device access then the - * handle returned must be used to unmap the frame. This is needed to - * drop the ref count on the frame. - */ -static u16 pending_grant_handles[MMAP_PAGES]; -#define pending_handle(_idx, _i) \ - (pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)]) -#define BLKBACK_INVALID_HANDLE (0xFFFF) -#endif +#define BLKBACK_INVALID_HANDLE (~0) -#ifdef CONFIG_XEN_BLKDEV_TAP_BE -/* - * If the tap driver is used, we may get pages belonging to either the tap - * or (more likely) the real frontend. The backend must specify which domain - * a given page belongs to in update_va_mapping though. For the moment, - * the tap rewrites the ID field of the request to contain the request index - * and the id of the real front end domain. - */ -#define BLKTAP_COOKIE 0xbeadfeed -static inline domid_t ID_TO_DOM(unsigned long id) { return (id >> 16); } -#endif +static unsigned long mmap_vstart; +static unsigned long *pending_vaddrs; +static grant_handle_t *pending_grant_handles; -static int do_block_io_op(blkif_t *blkif, int max_to_do); -static void dispatch_probe(blkif_t *blkif, blkif_request_t *req); -static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req); -static void make_response(blkif_t *blkif, unsigned long id, - unsigned short op, int st); +static inline int vaddr_pagenr(pending_req_t *req, int seg) +{ + return (req - pending_reqs) * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg; +} -static void fast_flush_area(int idx, int nr_pages) +static inline unsigned long vaddr(pending_req_t *req, int seg) { -#ifdef CONFIG_XEN_BLKDEV_GRANT - gnttab_op_t aop[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - unsigned int i, invcount = 0; - u16 handle; - - for ( i = 0; i < nr_pages; i++ ) - { - if ( BLKBACK_INVALID_HANDLE != ( handle = pending_handle(idx, i) ) ) - { - aop[i].u.unmap_grant_ref.host_virt_addr = MMAP_VADDR(idx, i); - aop[i].u.unmap_grant_ref.dev_bus_addr = 0; - aop[i].u.unmap_grant_ref.handle = handle; - pending_handle(idx, i) = BLKBACK_INVALID_HANDLE; - invcount++; - } - } - if ( unlikely(HYPERVISOR_grant_table_op( - GNTTABOP_unmap_grant_ref, aop, invcount))) - BUG(); -#else - - multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - int i; - - for ( i = 0; i < nr_pages; i++ ) - { - mcl[i].op = __HYPERVISOR_update_va_mapping; - mcl[i].args[0] = MMAP_VADDR(idx, i); - mcl[i].args[1] = 0; - mcl[i].args[2] = 0; - } - - mcl[nr_pages-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL; - if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) ) - BUG(); -#endif + return pending_vaddrs[vaddr_pagenr(req, seg)]; } +#define pending_handle(_req, _seg) \ + (pending_grant_handles[vaddr_pagenr(_req, _seg)]) + + +static int do_block_io_op(blkif_t *blkif); +static void dispatch_rw_block_io(blkif_t *blkif, + blkif_request_t *req, + pending_req_t *pending_req); +static void make_response(blkif_t *blkif, unsigned long id, + unsigned short op, int st); /****************************************************************** - * BLOCK-DEVICE SCHEDULER LIST MAINTENANCE + * misc small helpers */ +static pending_req_t* alloc_req(void) +{ + pending_req_t *req = NULL; + unsigned long flags; + + spin_lock_irqsave(&pending_free_lock, flags); + if (!list_empty(&pending_free)) { + req = list_entry(pending_free.next, pending_req_t, free_list); + list_del(&req->free_list); + } + spin_unlock_irqrestore(&pending_free_lock, flags); + return req; +} -static struct list_head blkio_schedule_list; -static spinlock_t blkio_schedule_list_lock; - -static int __on_blkdev_list(blkif_t *blkif) +static void free_req(pending_req_t *req) { - return blkif->blkdev_list.next != NULL; + unsigned long flags; + int was_empty; + + spin_lock_irqsave(&pending_free_lock, flags); + was_empty = list_empty(&pending_free); + list_add(&req->free_list, &pending_free); + spin_unlock_irqrestore(&pending_free_lock, flags); + if (was_empty) + wake_up(&pending_free_wq); } -static void remove_from_blkdev_list(blkif_t *blkif) +static void unplug_queue(blkif_t *blkif) { - unsigned long flags; - if ( !__on_blkdev_list(blkif) ) return; - spin_lock_irqsave(&blkio_schedule_list_lock, flags); - if ( __on_blkdev_list(blkif) ) - { - list_del(&blkif->blkdev_list); - blkif->blkdev_list.next = NULL; - blkif_put(blkif); - } - spin_unlock_irqrestore(&blkio_schedule_list_lock, flags); + if (blkif->plug == NULL) + return; + if (blkif->plug->unplug_fn) + blkif->plug->unplug_fn(blkif->plug); + blk_put_queue(blkif->plug); + blkif->plug = NULL; } -static void add_to_blkdev_list_tail(blkif_t *blkif) +static void plug_queue(blkif_t *blkif, struct bio *bio) { - unsigned long flags; - if ( __on_blkdev_list(blkif) ) return; - spin_lock_irqsave(&blkio_schedule_list_lock, flags); - if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) ) - { - list_add_tail(&blkif->blkdev_list, &blkio_schedule_list); - blkif_get(blkif); - } - spin_unlock_irqrestore(&blkio_schedule_list_lock, flags); + request_queue_t *q = bdev_get_queue(bio->bi_bdev); + + if (q == blkif->plug) + return; + unplug_queue(blkif); + blk_get_queue(q); + blkif->plug = q; } +static void fast_flush_area(pending_req_t *req) +{ + struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + unsigned int i, invcount = 0; + grant_handle_t handle; + int ret; + + for (i = 0; i < req->nr_pages; i++) { + handle = pending_handle(req, i); + if (handle == BLKBACK_INVALID_HANDLE) + continue; + gnttab_set_unmap_op(&unmap[i], vaddr(req, i), GNTMAP_host_map, + handle); + pending_handle(req, i) = BLKBACK_INVALID_HANDLE; + invcount++; + } + + ret = HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, unmap, invcount); + BUG_ON(ret); +} /****************************************************************** * SCHEDULER FUNCTIONS */ -static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait); +static void print_stats(blkif_t *blkif) +{ + printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d\n", + current->comm, blkif->st_oo_req, + blkif->st_rd_req, blkif->st_wr_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; +} -static int blkio_schedule(void *arg) +int blkif_schedule(void *arg) { - DECLARE_WAITQUEUE(wq, current); + blkif_t *blkif = arg; - blkif_t *blkif; - struct list_head *ent; + blkif_get(blkif); - daemonize( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - "xenblkd" -#endif - ); - - for ( ; ; ) - { - /* Wait for work to do. */ - add_wait_queue(&blkio_schedule_wait, &wq); - set_current_state(TASK_INTERRUPTIBLE); - if ( (NR_PENDING_REQS == MAX_PENDING_REQS) || - list_empty(&blkio_schedule_list) ) - schedule(); - __set_current_state(TASK_RUNNING); - remove_wait_queue(&blkio_schedule_wait, &wq); - - /* Queue up a batch of requests. */ - while ( (NR_PENDING_REQS < MAX_PENDING_REQS) && - !list_empty(&blkio_schedule_list) ) - { - ent = blkio_schedule_list.next; - blkif = list_entry(ent, blkif_t, blkdev_list); - blkif_get(blkif); - remove_from_blkdev_list(blkif); - if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) ) - add_to_blkdev_list_tail(blkif); - blkif_put(blkif); - } - - /* Push the batch through to disc. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - run_task_queue(&tq_disk); -#else - flush_plugged_queue(); -#endif - } -} + if (debug_lvl) + printk(KERN_DEBUG "%s: started\n", current->comm); -static void maybe_trigger_blkio_schedule(void) -{ - /* - * Needed so that two processes, who together make the following predicate - * true, don't both read stale values and evaluate the predicate - * incorrectly. Incredibly unlikely to stall the scheduler on x86, but... - */ - smp_mb(); - - if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) && - !list_empty(&blkio_schedule_list) ) - wake_up(&blkio_schedule_wait); -} + while (!kthread_should_stop()) { + wait_event_interruptible( + blkif->wq, + blkif->waiting_reqs || kthread_should_stop()); + wait_event_interruptible( + pending_free_wq, + !list_empty(&pending_free) || kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ + + if (do_block_io_op(blkif)) + blkif->waiting_reqs = 1; + unplug_queue(blkif); + if (log_stats && time_after(jiffies, blkif->st_print)) + print_stats(blkif); + } + if (log_stats) + print_stats(blkif); + if (debug_lvl) + printk(KERN_DEBUG "%s: exiting\n", current->comm); + + blkif->xenblkd = NULL; + blkif_put(blkif); + + return 0; +} /****************************************************************** * COMPLETION CALLBACK -- Called as bh->b_end_io() @@ -268,56 +245,45 @@ static void maybe_trigger_blkio_schedule(void) static void __end_block_io_op(pending_req_t *pending_req, int uptodate) { - unsigned long flags; - - /* An error fails the entire request. */ - if ( !uptodate ) - { - DPRINTK("Buffer not up-to-date at end of operation\n"); - pending_req->status = BLKIF_RSP_ERROR; - } - - if ( atomic_dec_and_test(&pending_req->pendcnt) ) - { - int pending_idx = pending_req - pending_reqs; - fast_flush_area(pending_idx, pending_req->nr_pages); - make_response(pending_req->blkif, pending_req->id, - pending_req->operation, pending_req->status); - blkif_put(pending_req->blkif); - spin_lock_irqsave(&pend_prod_lock, flags); - pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; - spin_unlock_irqrestore(&pend_prod_lock, flags); - maybe_trigger_blkio_schedule(); - } + /* An error fails the entire request. */ + if (!uptodate) { + DPRINTK("Buffer not up-to-date at end of operation\n"); + pending_req->status = BLKIF_RSP_ERROR; + } + + if (atomic_dec_and_test(&pending_req->pendcnt)) { + fast_flush_area(pending_req); + make_response(pending_req->blkif, pending_req->id, + pending_req->operation, pending_req->status); + blkif_put(pending_req->blkif); + free_req(pending_req); + } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static void end_block_io_op(struct buffer_head *bh, int uptodate) -{ - __end_block_io_op(bh->b_private, uptodate); - kmem_cache_free(buffer_head_cachep, bh); -} -#else static int end_block_io_op(struct bio *bio, unsigned int done, int error) { - if ( done || error ) - __end_block_io_op(bio->bi_private, (done && !error)); - bio_put(bio); - return error; + if (bio->bi_size != 0) + return 1; + __end_block_io_op(bio->bi_private, !error); + bio_put(bio); + return error; } -#endif /****************************************************************************** * NOTIFICATION FROM GUEST OS. */ +static void blkif_notify_work(blkif_t *blkif) +{ + blkif->waiting_reqs = 1; + wake_up(&blkif->wq); +} + irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) { - blkif_t *blkif = dev_id; - add_to_blkdev_list_tail(blkif); - maybe_trigger_blkio_schedule(); - return IRQ_HANDLED; + blkif_notify_work(dev_id); + return IRQ_HANDLED; } @@ -326,347 +292,170 @@ irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) * DOWNWARD CALLS -- These interface with the block-device layer proper. */ -static int do_block_io_op(blkif_t *blkif, int max_to_do) +static int do_block_io_op(blkif_t *blkif) { - blkif_back_ring_t *blk_ring = &blkif->blk_ring; - blkif_request_t *req; - RING_IDX i, rp; - int more_to_do = 0; - - rp = blk_ring->sring->req_prod; - rmb(); /* Ensure we see queued requests up to 'rp'. */ - - for ( i = blk_ring->req_cons; - (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i); - i++ ) - { - if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) ) - { - more_to_do = 1; - break; - } - - req = RING_GET_REQUEST(blk_ring, i); - switch ( req->operation ) - { - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - dispatch_rw_block_io(blkif, req); - break; - - case BLKIF_OP_PROBE: - dispatch_probe(blkif, req); - break; - - default: - DPRINTK("error: unknown block io operation [%d]\n", - req->operation); - make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); - break; - } - } - - blk_ring->req_cons = i; - return more_to_do; + blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_request_t *req; + pending_req_t *pending_req; + RING_IDX rc, rp; + int more_to_do = 0; + + rc = blk_ring->req_cons; + rp = blk_ring->sring->req_prod; + rmb(); /* Ensure we see queued requests up to 'rp'. */ + + while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) { + + pending_req = alloc_req(); + if (NULL == pending_req) { + blkif->st_oo_req++; + more_to_do = 1; + break; + } + + req = RING_GET_REQUEST(blk_ring, rc); + blk_ring->req_cons = ++rc; /* before make_response() */ + + switch (req->operation) { + case BLKIF_OP_READ: + blkif->st_rd_req++; + dispatch_rw_block_io(blkif, req, pending_req); + break; + case BLKIF_OP_WRITE: + blkif->st_wr_req++; + dispatch_rw_block_io(blkif, req, pending_req); + break; + default: + DPRINTK("error: unknown block io operation [%d]\n", + req->operation); + make_response(blkif, req->id, req->operation, + BLKIF_RSP_ERROR); + free_req(pending_req); + break; + } + } + return more_to_do; } -static void dispatch_probe(blkif_t *blkif, blkif_request_t *req) +static void dispatch_rw_block_io(blkif_t *blkif, + blkif_request_t *req, + pending_req_t *pending_req) { - int rsp = BLKIF_RSP_ERROR; - int pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - - /* We expect one buffer only. */ - if ( unlikely(req->nr_segments != 1) ) - goto out; - - /* Make sure the buffer is page-sized. */ - if ( (blkif_first_sect(req->frame_and_sects[0]) != 0) || - (blkif_last_sect(req->frame_and_sects[0]) != 7) ) - goto out; - -#ifdef CONFIG_XEN_BLKDEV_GRANT - { - gnttab_op_t op; - - op.u.map_grant_ref.host_virt_addr = MMAP_VADDR(pending_idx, 0); - op.u.map_grant_ref.flags = GNTMAP_host_map; - op.u.map_grant_ref.ref = blkif_gref_from_fas(req->frame_and_sects[0]); - op.u.map_grant_ref.dom = blkif->domid; - - if ( unlikely(HYPERVISOR_grant_table_op( - GNTTABOP_map_grant_ref, &op, 1))) - BUG(); - - if ( op.u.map_grant_ref.handle < 0 ) - goto out; - - pending_handle(pending_idx, 0) = op.u.map_grant_ref.handle; - } -#else /* else CONFIG_XEN_BLKDEV_GRANT */ - -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - /* Grab the real frontend out of the probe message. */ - if (req->frame_and_sects[1] == BLKTAP_COOKIE) - blkif->is_blktap = 1; -#endif - - -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - if ( HYPERVISOR_update_va_mapping_otherdomain( - MMAP_VADDR(pending_idx, 0), - (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL }, - 0, (blkif->is_blktap ? ID_TO_DOM(req->id) : blkif->domid) ) ) - - goto out; -#else - if ( HYPERVISOR_update_va_mapping_otherdomain( - MMAP_VADDR(pending_idx, 0), - (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL }, - 0, blkif->domid) ) - - goto out; -#endif -#endif /* endif CONFIG_XEN_BLKDEV_GRANT */ - - rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), - PAGE_SIZE / sizeof(vdisk_t)); - - out: - fast_flush_area(pending_idx, 1); - make_response(blkif, req->id, req->operation, rsp); -} - -static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) -{ - extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); - int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ; - unsigned long fas = 0; - int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - pending_req_t *pending_req; -#ifdef CONFIG_XEN_BLKDEV_GRANT - gnttab_op_t aop[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -#else - unsigned long remap_prot; - multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -#endif - struct phys_req preq; - struct { - unsigned long buf; unsigned int nsec; - } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - unsigned int nseg; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - struct buffer_head *bh; -#else - struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - int nbio = 0; - request_queue_t *q; -#endif - - /* Check that number of segments is sane. */ - nseg = req->nr_segments; - if ( unlikely(nseg == 0) || - unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) ) - { - DPRINTK("Bad number of segments in request (%d)\n", nseg); - goto bad_descriptor; - } - - preq.dev = req->device; - preq.sector_number = req->sector_number; - preq.nr_sects = 0; - -#ifdef CONFIG_XEN_BLKDEV_GRANT - for ( i = 0; i < nseg; i++ ) - { - fas = req->frame_and_sects[i]; - seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1; - - if ( seg[i].nsec <= 0 ) - goto bad_descriptor; - preq.nr_sects += seg[i].nsec; - - aop[i].u.map_grant_ref.host_virt_addr = MMAP_VADDR(pending_idx, i); - - aop[i].u.map_grant_ref.dom = blkif->domid; - aop[i].u.map_grant_ref.ref = blkif_gref_from_fas(fas); - aop[i].u.map_grant_ref.flags = ( GNTMAP_host_map | - ( ( operation == READ ) ? - 0 : GNTMAP_readonly ) ); - } - - if ( unlikely(HYPERVISOR_grant_table_op( - GNTTABOP_map_grant_ref, aop, nseg))) - BUG(); - - for ( i = 0; i < nseg; i++ ) - { - if ( unlikely(aop[i].u.map_grant_ref.handle < 0) ) - { - DPRINTK("invalid buffer -- could not remap it\n"); - fast_flush_area(pending_idx, nseg); - goto bad_descriptor; - } - - phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] = - FOREIGN_FRAME(aop[i].u.map_grant_ref.dev_bus_addr); - - pending_handle(pending_idx, i) = aop[i].u.map_grant_ref.handle; - } -#endif - - for ( i = 0; i < nseg; i++ ) - { - fas = req->frame_and_sects[i]; -#ifdef CONFIG_XEN_BLKDEV_GRANT - seg[i].buf = (aop[i].u.map_grant_ref.dev_bus_addr << PAGE_SHIFT) | - (blkif_first_sect(fas) << 9); -#else - seg[i].buf = (fas & PAGE_MASK) | (blkif_first_sect(fas) << 9); - seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1; - if ( seg[i].nsec <= 0 ) - goto bad_descriptor; - preq.nr_sects += seg[i].nsec; -#endif - } - - if ( vbd_translate(&preq, blkif, operation) != 0 ) - { - DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", - operation == READ ? "read" : "write", preq.sector_number, - preq.sector_number + preq.nr_sects, preq.dev); - goto bad_descriptor; - } - -#ifndef CONFIG_XEN_BLKDEV_GRANT - if ( operation == READ ) - remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW; - else - remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED; - - for ( i = 0; i < nseg; i++ ) - { - mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain; - mcl[i].args[0] = MMAP_VADDR(pending_idx, i); - mcl[i].args[1] = (seg[i].buf & PAGE_MASK) | remap_prot; - mcl[i].args[2] = 0; - mcl[i].args[3] = blkif->domid; -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - if ( blkif->is_blktap ) - mcl[i].args[3] = ID_TO_DOM(req->id); -#endif - phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] = - FOREIGN_FRAME(seg[i].buf >> PAGE_SHIFT); - } - - BUG_ON(HYPERVISOR_multicall(mcl, nseg) != 0); - - for ( i = 0; i < nseg; i++ ) - { - if ( unlikely(mcl[i].args[5] != 0) ) - { - DPRINTK("invalid buffer -- could not remap it\n"); - fast_flush_area(pending_idx, nseg); - goto bad_descriptor; - } - } -#endif /* end ifndef CONFIG_XEN_BLKDEV_GRANT */ - - pending_req = &pending_reqs[pending_idx]; - pending_req->blkif = blkif; - pending_req->id = req->id; - pending_req->operation = operation; - pending_req->status = BLKIF_RSP_OKAY; - pending_req->nr_pages = nseg; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - - atomic_set(&pending_req->pendcnt, nseg); - pending_cons++; - blkif_get(blkif); - - for ( i = 0; i < nseg; i++ ) - { - bh = kmem_cache_alloc(buffer_head_cachep, GFP_KERNEL); - if ( unlikely(bh == NULL) ) - { - __end_block_io_op(pending_req, 0); - continue; - } - - memset(bh, 0, sizeof (struct buffer_head)); - - init_waitqueue_head(&bh->b_wait); - bh->b_size = seg[i].nsec << 9; - bh->b_dev = preq.dev; - bh->b_rdev = preq.dev; - bh->b_rsector = (unsigned long)preq.sector_number; - bh->b_data = (char *)MMAP_VADDR(pending_idx, i) + - (seg[i].buf & ~PAGE_MASK); - bh->b_page = virt_to_page(MMAP_VADDR(pending_idx, i)); - bh->b_end_io = end_block_io_op; - bh->b_private = pending_req; - - bh->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | - (1 << BH_Req) | (1 << BH_Launder); - if ( operation == WRITE ) - bh->b_state |= (1 << BH_JBD) | (1 << BH_Req) | (1 << BH_Uptodate); - - atomic_set(&bh->b_count, 1); - - /* Dispatch a single request. We'll flush it to disc later. */ - generic_make_request(operation, bh); - - preq.sector_number += seg[i].nsec; - } - -#else - - for ( i = 0; i < nseg; i++ ) - { - while ( (bio == NULL) || - (bio_add_page(bio, - virt_to_page(MMAP_VADDR(pending_idx, i)), - seg[i].nsec << 9, - seg[i].buf & ~PAGE_MASK) == 0) ) - { - bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i); - if ( unlikely(bio == NULL) ) - { - for ( i = 0; i < (nbio-1); i++ ) - bio_put(biolist[i]); - fast_flush_area(pending_idx, nseg); - goto bad_descriptor; - } - - bio->bi_bdev = preq.bdev; - bio->bi_private = pending_req; - bio->bi_end_io = end_block_io_op; - bio->bi_sector = preq.sector_number; - } - - preq.sector_number += seg[i].nsec; - } - - if ( (q = bdev_get_queue(bio->bi_bdev)) != plugged_queue ) - { - flush_plugged_queue(); - blk_get_queue(q); - plugged_queue = q; - } - - atomic_set(&pending_req->pendcnt, nbio); - pending_cons++; - blkif_get(blkif); - - for ( i = 0; i < nbio; i++ ) - submit_bio(operation, biolist[i]); - -#endif - - return; - - bad_descriptor: - make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); + int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ; + struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + struct phys_req preq; + struct { + unsigned long buf; unsigned int nsec; + } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + unsigned int nseg; + struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int ret, i, nbio = 0; + + /* Check that number of segments is sane. */ + nseg = req->nr_segments; + if (unlikely(nseg == 0) || + unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { + DPRINTK("Bad number of segments in request (%d)\n", nseg); + goto fail_response; + } + + preq.dev = req->handle; + preq.sector_number = req->sector_number; + preq.nr_sects = 0; + + pending_req->blkif = blkif; + pending_req->id = req->id; + pending_req->operation = operation; + pending_req->status = BLKIF_RSP_OKAY; + pending_req->nr_pages = nseg; + + for (i = 0; i < nseg; i++) { + uint32_t flags; + + seg[i].nsec = req->seg[i].last_sect - + req->seg[i].first_sect + 1; + + if ((req->seg[i].last_sect >= (PAGE_SIZE >> 9)) || + (seg[i].nsec <= 0)) + goto fail_response; + preq.nr_sects += seg[i].nsec; + + flags = GNTMAP_host_map; + if ( operation == WRITE ) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags, + req->seg[i].gref, blkif->domid); + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); + BUG_ON(ret); + + for (i = 0; i < nseg; i++) { + if (unlikely(map[i].status != 0)) { + DPRINTK("invalid buffer -- could not remap it\n"); + goto fail_flush; + } + + pending_handle(pending_req, i) = map[i].handle; + set_phys_to_machine(__pa(vaddr( + pending_req, i)) >> PAGE_SHIFT, + FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); + seg[i].buf = map[i].dev_bus_addr | + (req->seg[i].first_sect << 9); + } + + if (vbd_translate(&preq, blkif, operation) != 0) { + DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", + operation == READ ? "read" : "write", + preq.sector_number, + preq.sector_number + preq.nr_sects, preq.dev); + goto fail_flush; + } + + for (i = 0; i < nseg; i++) { + if (((int)preq.sector_number|(int)seg[i].nsec) & + ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) { + DPRINTK("Misaligned I/O request from domain %d", + blkif->domid); + goto fail_put_bio; + } + + while ((bio == NULL) || + (bio_add_page(bio, + virt_to_page(vaddr(pending_req, i)), + seg[i].nsec << 9, + seg[i].buf & ~PAGE_MASK) == 0)) { + bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i); + if (unlikely(bio == NULL)) + goto fail_put_bio; + + bio->bi_bdev = preq.bdev; + bio->bi_private = pending_req; + bio->bi_end_io = end_block_io_op; + bio->bi_sector = preq.sector_number; + } + + preq.sector_number += seg[i].nsec; + } + + plug_queue(blkif, bio); + atomic_set(&pending_req->pendcnt, nbio); + blkif_get(blkif); + + for (i = 0; i < nbio; i++) + submit_bio(operation, biolist[i]); + + return; + + fail_put_bio: + for (i = 0; i < (nbio-1); i++) + bio_put(biolist[i]); + fail_flush: + fast_flush_area(pending_req); + fail_response: + make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + free_req(pending_req); } @@ -677,75 +466,101 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) static void make_response(blkif_t *blkif, unsigned long id, - unsigned short op, int st) + unsigned short op, int st) { - blkif_response_t *resp; - unsigned long flags; - blkif_back_ring_t *blk_ring = &blkif->blk_ring; - - /* Place on the response ring for the relevant domain. */ - spin_lock_irqsave(&blkif->blk_ring_lock, flags); - resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); - resp->id = id; - resp->operation = op; - resp->status = st; - wmb(); /* Ensure other side can see the response fields. */ - blk_ring->rsp_prod_pvt++; - RING_PUSH_RESPONSES(blk_ring); - spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); - - /* Kick the relevant domain. */ - notify_via_evtchn(blkif->evtchn); -} - -void blkif_deschedule(blkif_t *blkif) -{ - remove_from_blkdev_list(blkif); + blkif_response_t *resp; + unsigned long flags; + blkif_back_ring_t *blk_ring = &blkif->blk_ring; + int more_to_do = 0; + int notify; + + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + + /* Place on the response ring for the relevant domain. */ + resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); + resp->id = id; + resp->operation = op; + resp->status = st; + blk_ring->rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify); + + if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) { + /* + * Tail check for pending requests. Allows frontend to avoid + * notifications if requests are already in flight (lower + * overheads and promotes batching). + */ + RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do); + + } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) { + more_to_do = 1; + + } + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); + + if (more_to_do) + blkif_notify_work(blkif); + if (notify) + notify_remote_via_irq(blkif->irq); } static int __init blkif_init(void) { - int i; - - if ( !(xen_start_info.flags & SIF_INITDOMAIN) && - !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) ) - return 0; - - blkif_interface_init(); - - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) - BUG(); - - pending_cons = 0; - pending_prod = MAX_PENDING_REQS; - memset(pending_reqs, 0, sizeof(pending_reqs)); - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - pending_ring[i] = i; - - spin_lock_init(&blkio_schedule_list_lock); - INIT_LIST_HEAD(&blkio_schedule_list); - - if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 ) - BUG(); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - buffer_head_cachep = kmem_cache_create( - "buffer_head_cache", sizeof(struct buffer_head), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + struct page *page; + int i; + + if (!is_running_on_xen()) + return -ENODEV; + + mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; + +#ifdef CONFIG_XEN_IA64_DOM0_NON_VP + extern unsigned long alloc_empty_foreign_map_page_range( + unsigned long pages); + mmap_vstart = (unsigned long) + alloc_empty_foreign_map_page_range(mmap_pages); +#else /* ! ia64 */ + page = balloon_alloc_empty_page_range(mmap_pages); + if (page == NULL) + return -ENOMEM; + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); #endif - blkif_ctrlif_init(); + pending_reqs = kmalloc(sizeof(pending_reqs[0]) * + blkif_reqs, GFP_KERNEL); + pending_grant_handles = kmalloc(sizeof(pending_grant_handles[0]) * + mmap_pages, GFP_KERNEL); + pending_vaddrs = kmalloc(sizeof(pending_vaddrs[0]) * + mmap_pages, GFP_KERNEL); + if (!pending_reqs || !pending_grant_handles || !pending_vaddrs) { + kfree(pending_reqs); + kfree(pending_grant_handles); + kfree(pending_vaddrs); + printk("%s: out of memory\n", __FUNCTION__); + return -ENOMEM; + } + + blkif_interface_init(); + + printk("%s: reqs=%d, pages=%d, mmap_vstart=0x%lx\n", + __FUNCTION__, blkif_reqs, mmap_pages, mmap_vstart); + BUG_ON(mmap_vstart == 0); + for (i = 0; i < mmap_pages; i++) { + pending_vaddrs[i] = mmap_vstart + (i << PAGE_SHIFT); + pending_grant_handles[i] = BLKBACK_INVALID_HANDLE; + } + + memset(pending_reqs, 0, sizeof(pending_reqs)); + INIT_LIST_HEAD(&pending_free); + + for (i = 0; i < blkif_reqs; i++) + list_add_tail(&pending_reqs[i].free_list, &pending_free); -#ifdef CONFIG_XEN_BLKDEV_GRANT - memset( pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES ); - printk(KERN_ALERT "Blkif backend is using grant tables.\n"); -#endif + blkif_xenbus_init(); -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n"); -#endif - - return 0; + return 0; } -__initcall(blkif_init); +module_init(blkif_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h index a698e01c6..d057f7924 100644 --- a/drivers/xen/blkback/common.h +++ b/drivers/xen/blkback/common.h @@ -1,3 +1,28 @@ +/* + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ #ifndef __BLKIF__BACKEND__COMMON_H__ #define __BLKIF__BACKEND__COMMON_H__ @@ -5,100 +30,105 @@ #include #include #include -#include #include #include #include +#include +#include #include #include #include -#include -#include -#include -#include - -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define ASSERT(_p) ((void)0) -#define DPRINTK(_f, _a...) ((void)0) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -typedef struct rb_root rb_root_t; -typedef struct rb_node rb_node_t; -#else -struct block_device; -#endif +#include +#include +#include +#include +#include +#include + +#define DPRINTK(_f, _a...) \ + pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) + +struct vbd { + blkif_vdev_t handle; /* what the domain refers to this vbd as */ + unsigned char readonly; /* Non-zero -> read-only */ + unsigned char type; /* VDISK_xxx */ + u32 pdevice; /* phys device that this vbd maps to */ + struct block_device *bdev; +}; + +struct backend_info; typedef struct blkif_st { - /* Unique identifier for this interface. */ - domid_t domid; - unsigned int handle; - /* Physical parameters of the comms window. */ - unsigned long shmem_frame; - unsigned int evtchn; - int irq; - /* Comms information. */ - blkif_back_ring_t blk_ring; - /* VBDs attached to this interface. */ - rb_root_t vbd_rb; /* Mapping from 16-bit vdevices to VBDs.*/ - spinlock_t vbd_lock; /* Protects VBD mapping. */ - /* Private fields. */ - enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; - /* - * DISCONNECT response is deferred until pending requests are ack'ed. - * We therefore need to store the id from the original request. - */ - u8 disconnect_rspid; -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - /* Is this a blktap frontend */ - unsigned int is_blktap; -#endif - struct blkif_st *hash_next; - struct list_head blkdev_list; - spinlock_t blk_ring_lock; - atomic_t refcnt; - - struct work_struct work; + /* Unique identifier for this interface. */ + domid_t domid; + unsigned int handle; + /* Physical parameters of the comms window. */ + unsigned int evtchn; + unsigned int irq; + /* Comms information. */ + blkif_back_ring_t blk_ring; + struct vm_struct *blk_ring_area; + /* The VBD attached to this interface. */ + struct vbd vbd; + /* Back pointer to the backend_info. */ + struct backend_info *be; + /* Private fields. */ + spinlock_t blk_ring_lock; + atomic_t refcnt; + + wait_queue_head_t wq; + struct task_struct *xenblkd; + unsigned int waiting_reqs; + request_queue_t *plug; + + /* statistics */ + unsigned long st_print; + int st_rd_req; + int st_wr_req; + int st_oo_req; + + wait_queue_head_t waiting_to_free; + + grant_handle_t shmem_handle; + grant_ref_t shmem_ref; } blkif_t; -void blkif_create(blkif_be_create_t *create); -void blkif_destroy(blkif_be_destroy_t *destroy); -void blkif_connect(blkif_be_connect_t *connect); -int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id); -void blkif_disconnect_complete(blkif_t *blkif); -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle); +blkif_t *blkif_alloc(domid_t domid); +void blkif_disconnect(blkif_t *blkif); +void blkif_free(blkif_t *blkif); +int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn); + #define blkif_get(_b) (atomic_inc(&(_b)->refcnt)) -#define blkif_put(_b) \ - do { \ - if ( atomic_dec_and_test(&(_b)->refcnt) ) \ - blkif_disconnect_complete(_b); \ - } while (0) +#define blkif_put(_b) \ + do { \ + if (atomic_dec_and_test(&(_b)->refcnt)) \ + wake_up(&(_b)->waiting_to_free);\ + } while (0) + +/* Create a vbd. */ +int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, unsigned major, + unsigned minor, int readonly); +void vbd_free(struct vbd *vbd); -void vbd_create(blkif_be_vbd_create_t *create); -void vbd_destroy(blkif_be_vbd_destroy_t *delete); -int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds); -void destroy_all_vbds(blkif_t *blkif); +unsigned long vbd_size(struct vbd *vbd); +unsigned int vbd_info(struct vbd *vbd); +unsigned long vbd_secsize(struct vbd *vbd); struct phys_req { - unsigned short dev; - unsigned short nr_sects; - struct block_device *bdev; - blkif_sector_t sector_number; + unsigned short dev; + unsigned short nr_sects; + struct block_device *bdev; + blkif_sector_t sector_number; }; int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation); void blkif_interface_init(void); -void blkif_ctrlif_init(void); -void blkif_deschedule(blkif_t *blkif); +void blkif_xenbus_init(void); irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); +int blkif_schedule(void *arg); #endif /* __BLKIF__BACKEND__COMMON_H__ */ diff --git a/drivers/xen/blkback/interface.c b/drivers/xen/blkback/interface.c index 46d55d1fd..53b4764c4 100644 --- a/drivers/xen/blkback/interface.c +++ b/drivers/xen/blkback/interface.c @@ -4,246 +4,168 @@ * Block-device interface management. * * Copyright (c) 2004, Keir Fraser + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ #include "common.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#endif - -#define BLKIF_HASHSZ 1024 -#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1)) +#include +#include static kmem_cache_t *blkif_cachep; -static blkif_t *blkif_hash[BLKIF_HASHSZ]; -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle) +blkif_t *blkif_alloc(domid_t domid) { - blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)]; - while ( (blkif != NULL) && - ((blkif->domid != domid) || (blkif->handle != handle)) ) - blkif = blkif->hash_next; - return blkif; -} + blkif_t *blkif; -static void __blkif_disconnect_complete(void *arg) -{ - blkif_t *blkif = (blkif_t *)arg; - ctrl_msg_t cmsg; - blkif_be_disconnect_t disc; - - /* - * These can't be done in blkif_disconnect() because at that point there - * may be outstanding requests at the disc whose asynchronous responses - * must still be notified to the remote driver. - */ - unbind_evtchn_from_irq(blkif->evtchn); - vfree(blkif->blk_ring.sring); - - /* Construct the deferred response message. */ - cmsg.type = CMSG_BLKIF_BE; - cmsg.subtype = CMSG_BLKIF_BE_DISCONNECT; - cmsg.id = blkif->disconnect_rspid; - cmsg.length = sizeof(blkif_be_disconnect_t); - disc.domid = blkif->domid; - disc.blkif_handle = blkif->handle; - disc.status = BLKIF_BE_STATUS_OKAY; - memcpy(cmsg.msg, &disc, sizeof(disc)); - - /* - * Make sure message is constructed /before/ status change, because - * after the status change the 'blkif' structure could be deallocated at - * any time. Also make sure we send the response /after/ status change, - * as otherwise a subsequent CONNECT request could spuriously fail if - * another CPU doesn't see the status change yet. - */ - mb(); - if ( blkif->status != DISCONNECTING ) - BUG(); - blkif->status = DISCONNECTED; - mb(); - - /* Send the successful response. */ - ctrl_if_send_response(&cmsg); + blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL); + if (!blkif) + return ERR_PTR(-ENOMEM); + + memset(blkif, 0, sizeof(*blkif)); + blkif->domid = domid; + spin_lock_init(&blkif->blk_ring_lock); + atomic_set(&blkif->refcnt, 1); + init_waitqueue_head(&blkif->wq); + blkif->st_print = jiffies; + init_waitqueue_head(&blkif->waiting_to_free); + + return blkif; } -void blkif_disconnect_complete(blkif_t *blkif) +static int map_frontend_page(blkif_t *blkif, unsigned long shared_page) { - INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif); - schedule_work(&blkif->work); + struct gnttab_map_grant_ref op; + int ret; + + gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, shared_page, blkif->domid); + + lock_vm_area(blkif->blk_ring_area); + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); + unlock_vm_area(blkif->blk_ring_area); + BUG_ON(ret); + + if (op.status) { + DPRINTK(" Grant table operation failure !\n"); + return op.status; + } + + blkif->shmem_ref = shared_page; + blkif->shmem_handle = op.handle; + + return 0; } -void blkif_create(blkif_be_create_t *create) +static void unmap_frontend_page(blkif_t *blkif) { - domid_t domid = create->domid; - unsigned int handle = create->blkif_handle; - blkif_t **pblkif, *blkif; - - if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL ) - { - DPRINTK("Could not create blkif: out of memory\n"); - create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - memset(blkif, 0, sizeof(*blkif)); - blkif->domid = domid; - blkif->handle = handle; - blkif->status = DISCONNECTED; - spin_lock_init(&blkif->vbd_lock); - spin_lock_init(&blkif->blk_ring_lock); - atomic_set(&blkif->refcnt, 0); - - pblkif = &blkif_hash[BLKIF_HASH(domid, handle)]; - while ( *pblkif != NULL ) - { - if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) ) - { - DPRINTK("Could not create blkif: already exists\n"); - create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS; - kmem_cache_free(blkif_cachep, blkif); - return; - } - pblkif = &(*pblkif)->hash_next; - } - - blkif->hash_next = *pblkif; - *pblkif = blkif; - - DPRINTK("Successfully created blkif\n"); - create->status = BLKIF_BE_STATUS_OKAY; + struct gnttab_unmap_grant_ref op; + int ret; + + gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, blkif->shmem_handle); + + lock_vm_area(blkif->blk_ring_area); + ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); + unlock_vm_area(blkif->blk_ring_area); + BUG_ON(ret); } -void blkif_destroy(blkif_be_destroy_t *destroy) +int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) { - domid_t domid = destroy->domid; - unsigned int handle = destroy->blkif_handle; - blkif_t **pblkif, *blkif; - - pblkif = &blkif_hash[BLKIF_HASH(domid, handle)]; - while ( (blkif = *pblkif) != NULL ) - { - if ( (blkif->domid == domid) && (blkif->handle == handle) ) - { - if ( blkif->status != DISCONNECTED ) - goto still_connected; - goto destroy; - } - pblkif = &blkif->hash_next; - } - - destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - - still_connected: - destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED; - return; - - destroy: - *pblkif = blkif->hash_next; - destroy_all_vbds(blkif); - kmem_cache_free(blkif_cachep, blkif); - destroy->status = BLKIF_BE_STATUS_OKAY; + blkif_sring_t *sring; + int err; + struct evtchn_bind_interdomain bind_interdomain; + + /* Already connected through? */ + if (blkif->irq) + return 0; + + if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL ) + return -ENOMEM; + + err = map_frontend_page(blkif, shared_page); + if (err) { + free_vm_area(blkif->blk_ring_area); + return err; + } + + bind_interdomain.remote_dom = blkif->domid; + bind_interdomain.remote_port = evtchn; + + err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, + &bind_interdomain); + if (err) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + return err; + } + + blkif->evtchn = bind_interdomain.local_port; + + sring = (blkif_sring_t *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); + + blkif->irq = bind_evtchn_to_irqhandler( + blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); + + return 0; } -void blkif_connect(blkif_be_connect_t *connect) +void blkif_disconnect(blkif_t *blkif) { - domid_t domid = connect->domid; - unsigned int handle = connect->blkif_handle; - unsigned int evtchn = connect->evtchn; - unsigned long shmem_frame = connect->shmem_frame; - struct vm_struct *vma; - pgprot_t prot; - int error; - blkif_t *blkif; - blkif_sring_t *sring; - - blkif = blkif_find_by_handle(domid, handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n", - connect->domid, connect->blkif_handle); - connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) - { - connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED); - error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr), - shmem_frame<status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - else if ( error == -EFAULT ) - connect->status = BLKIF_BE_STATUS_MAPPING_ERROR; - else - connect->status = BLKIF_BE_STATUS_ERROR; - vfree(vma->addr); - return; - } - - if ( blkif->status != DISCONNECTED ) - { - connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED; - vfree(vma->addr); - return; - } - sring = (blkif_sring_t *)vma->addr; - SHARED_RING_INIT(sring); - BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); - - blkif->evtchn = evtchn; - blkif->irq = bind_evtchn_to_irq(evtchn); - blkif->shmem_frame = shmem_frame; - blkif->status = CONNECTED; - blkif_get(blkif); - - request_irq(blkif->irq, blkif_be_int, 0, "blkif-backend", blkif); - - connect->status = BLKIF_BE_STATUS_OKAY; + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + blkif->xenblkd = NULL; + } + + atomic_dec(&blkif->refcnt); + wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); + atomic_inc(&blkif->refcnt); + + if (blkif->irq) { + unbind_from_irqhandler(blkif->irq, blkif); + blkif->irq = 0; + } + + if (blkif->blk_ring.sring) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_ring.sring = NULL; + } } -int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id) +void blkif_free(blkif_t *blkif) { - domid_t domid = disconnect->domid; - unsigned int handle = disconnect->blkif_handle; - blkif_t *blkif; - - blkif = blkif_find_by_handle(domid, handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("blkif_disconnect attempted for non-existent blkif" - " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle); - disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return 1; /* Caller will send response error message. */ - } - - if ( blkif->status == CONNECTED ) - { - blkif->status = DISCONNECTING; - blkif->disconnect_rspid = rsp_id; - wmb(); /* Let other CPUs see the status change. */ - free_irq(blkif->irq, blkif); - blkif_deschedule(blkif); - blkif_put(blkif); - return 0; /* Caller should not send response message. */ - } - - disconnect->status = BLKIF_BE_STATUS_OKAY; - return 1; + if (!atomic_dec_and_test(&blkif->refcnt)) + BUG(); + kmem_cache_free(blkif_cachep, blkif); } void __init blkif_interface_init(void) { - blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), - 0, 0, NULL, NULL); - memset(blkif_hash, 0, sizeof(blkif_hash)); + blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), + 0, 0, NULL, NULL); } diff --git a/drivers/xen/blkback/vbd.c b/drivers/xen/blkback/vbd.c index f5ee589ee..a809b04cd 100644 --- a/drivers/xen/blkback/vbd.c +++ b/drivers/xen/blkback/vbd.c @@ -3,285 +3,117 @@ * * Routines for managing virtual block devices (VBDs). * - * NOTE: vbd_lock protects updates to the rb_tree against concurrent lookups - * in vbd_translate. All other lookups are implicitly protected because the - * only caller (the control message dispatch routine) serializes the calls. - * * Copyright (c) 2003-2005, Keir Fraser & Steve Hand + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ #include "common.h" +#include -struct vbd { - blkif_vdev_t vdevice; /* what the domain refers to this vbd as */ - unsigned char readonly; /* Non-zero -> read-only */ - unsigned char type; /* VDISK_TYPE_xxx */ - blkif_pdev_t pdevice; /* phys device that this vbd maps to */ - struct block_device *bdev; - rb_node_t rb; /* for linking into R-B tree lookup struct */ -}; +#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ + (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static inline dev_t vbd_map_devnum(blkif_pdev_t cookie) -{ return MKDEV(cookie>>8, cookie&0xff); } -#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ - (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity) -#define bdev_put(_b) blkdev_put(_b) -#else -#define vbd_sz(_v) (blk_size[MAJOR((_v)->pdevice)][MINOR((_v)->pdevice)]*2) -#define bdev_put(_b) ((void)0) -#endif - -void vbd_create(blkif_be_vbd_create_t *create) +unsigned long vbd_size(struct vbd *vbd) { - struct vbd *vbd; - rb_node_t **rb_p, *rb_parent = NULL; - blkif_t *blkif; - blkif_vdev_t vdevice = create->vdevice; - - blkif = blkif_find_by_handle(create->domid, create->blkif_handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("vbd_create attempted for non-existent blkif (%u,%u)\n", - create->domid, create->blkif_handle); - create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - rb_p = &blkif->vbd_rb.rb_node; - while ( *rb_p != NULL ) - { - rb_parent = *rb_p; - vbd = rb_entry(rb_parent, struct vbd, rb); - if ( vdevice < vbd->vdevice ) - { - rb_p = &rb_parent->rb_left; - } - else if ( vdevice > vbd->vdevice ) - { - rb_p = &rb_parent->rb_right; - } - else - { - DPRINTK("vbd_create attempted for already existing vbd\n"); - create->status = BLKIF_BE_STATUS_VBD_EXISTS; - return; - } - } - - if ( unlikely((vbd = kmalloc(sizeof(struct vbd), GFP_KERNEL)) == NULL) ) - { - DPRINTK("vbd_create: out of memory\n"); - create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - vbd->vdevice = vdevice; - vbd->readonly = create->readonly; - vbd->type = VDISK_TYPE_DISK | VDISK_FLAG_VIRT; - - /* Mask to 16-bit for compatibility with old tools */ - vbd->pdevice = create->pdevice & 0xffff; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - vbd->bdev = open_by_devnum( - vbd_map_devnum(vbd->pdevice), - vbd->readonly ? FMODE_READ : FMODE_WRITE); - if ( IS_ERR(vbd->bdev) ) - { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); - create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; - return; - } - - if ( (vbd->bdev->bd_disk == NULL) ) - { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); - create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; - bdev_put(vbd->bdev); - return; - } -#else - if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) ) - { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); - create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; - return; - } -#endif - - spin_lock(&blkif->vbd_lock); - rb_link_node(&vbd->rb, rb_parent, rb_p); - rb_insert_color(&vbd->rb, &blkif->vbd_rb); - spin_unlock(&blkif->vbd_lock); - - DPRINTK("Successful creation of vdev=%04x (dom=%u)\n", - vdevice, create->domid); - create->status = BLKIF_BE_STATUS_OKAY; + return vbd_sz(vbd); } - -void vbd_destroy(blkif_be_vbd_destroy_t *destroy) +unsigned int vbd_info(struct vbd *vbd) { - blkif_t *blkif; - struct vbd *vbd; - rb_node_t *rb; - blkif_vdev_t vdevice = destroy->vdevice; - - blkif = blkif_find_by_handle(destroy->domid, destroy->blkif_handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("vbd_destroy attempted for non-existent blkif (%u,%u)\n", - destroy->domid, destroy->blkif_handle); - destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - rb = blkif->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, struct vbd, rb); - if ( vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - goto found; - } - - destroy->status = BLKIF_BE_STATUS_VBD_NOT_FOUND; - return; - - found: - spin_lock(&blkif->vbd_lock); - rb_erase(rb, &blkif->vbd_rb); - spin_unlock(&blkif->vbd_lock); - bdev_put(vbd->bdev); - kfree(vbd); + return vbd->type | (vbd->readonly?VDISK_READONLY:0); } - -void destroy_all_vbds(blkif_t *blkif) +unsigned long vbd_secsize(struct vbd *vbd) { - struct vbd *vbd; - rb_node_t *rb; - - spin_lock(&blkif->vbd_lock); - - while ( (rb = blkif->vbd_rb.rb_node) != NULL ) - { - vbd = rb_entry(rb, struct vbd, rb); - rb_erase(rb, &blkif->vbd_rb); - spin_unlock(&blkif->vbd_lock); - bdev_put(vbd->bdev); - kfree(vbd); - spin_lock(&blkif->vbd_lock); - } - - spin_unlock(&blkif->vbd_lock); + return bdev_hardsect_size(vbd->bdev); } - -static void vbd_probe_single( - blkif_t *blkif, vdisk_t *vbd_info, struct vbd *vbd) +int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major, + unsigned minor, int readonly) { - vbd_info->device = vbd->vdevice; - vbd_info->info = vbd->type | (vbd->readonly ? VDISK_FLAG_RO : 0); - vbd_info->capacity = vbd_sz(vbd); + struct vbd *vbd; + struct block_device *bdev; + + vbd = &blkif->vbd; + vbd->handle = handle; + vbd->readonly = readonly; + vbd->type = 0; + + vbd->pdevice = MKDEV(major, minor); + + bdev = open_by_devnum(vbd->pdevice, + vbd->readonly ? FMODE_READ : FMODE_WRITE); + + if (IS_ERR(bdev)) { + DPRINTK("vbd_creat: device %08x could not be opened.\n", + vbd->pdevice); + return -ENOENT; + } + + vbd->bdev = bdev; + + if (vbd->bdev->bd_disk == NULL) { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", + vbd->pdevice); + vbd_free(vbd); + return -ENOENT; + } + + if (vbd->bdev->bd_disk->flags & GENHD_FL_CD) + vbd->type |= VDISK_CDROM; + if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) + vbd->type |= VDISK_REMOVABLE; + + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return 0; } - -int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds) +void vbd_free(struct vbd *vbd) { - int rc = 0, nr_vbds = 0; - rb_node_t *rb; - - spin_lock(&blkif->vbd_lock); - - if ( (rb = blkif->vbd_rb.rb_node) == NULL ) - goto out; - - new_subtree: - /* STEP 1. Find least node (it'll be left-most). */ - while ( rb->rb_left != NULL ) - rb = rb->rb_left; - - for ( ; ; ) - { - /* STEP 2. Dealt with left subtree. Now process current node. */ - vbd_probe_single(blkif, &vbd_info[nr_vbds], - rb_entry(rb, struct vbd, rb)); - if ( ++nr_vbds == max_vbds ) - goto out; - - /* STEP 3. Process right subtree, if any. */ - if ( rb->rb_right != NULL ) - { - rb = rb->rb_right; - goto new_subtree; - } - - /* STEP 4. Done both subtrees. Head back through ancesstors. */ - for ( ; ; ) - { - /* We're done when we get back to the root node. */ - if ( rb->rb_parent == NULL ) - goto out; - /* If we are left of parent, then parent is next to process. */ - if ( rb->rb_parent->rb_left == rb ) - break; - /* If we are right of parent, then we climb to grandparent. */ - rb = rb->rb_parent; - } - - rb = rb->rb_parent; - } - - out: - spin_unlock(&blkif->vbd_lock); - return (rc == 0) ? nr_vbds : rc; + if (vbd->bdev) + blkdev_put(vbd->bdev); + vbd->bdev = NULL; } - int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation) { - struct vbd *vbd; - rb_node_t *rb; - int rc = -EACCES; - - /* Take the vbd_lock because another thread could be updating the tree. */ - spin_lock(&blkif->vbd_lock); - - rb = blkif->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, struct vbd, rb); - if ( req->dev < vbd->vdevice ) - rb = rb->rb_left; - else if ( req->dev > vbd->vdevice ) - rb = rb->rb_right; - else - goto found; - } - - DPRINTK("vbd_translate; domain %u attempted to access " - "non-existent VBD.\n", blkif->domid); - rc = -ENODEV; - goto out; - - found: + struct vbd *vbd = &blkif->vbd; + int rc = -EACCES; - if ( (operation == WRITE) && vbd->readonly ) - goto out; + if ((operation == WRITE) && vbd->readonly) + goto out; - if ( unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)) ) - goto out; + if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) + goto out; - req->dev = vbd->pdevice; - req->bdev = vbd->bdev; - rc = 0; + req->dev = vbd->pdevice; + req->bdev = vbd->bdev; + rc = 0; out: - spin_unlock(&blkif->vbd_lock); - return rc; + return rc; } diff --git a/drivers/xen/blkfront/Makefile b/drivers/xen/blkfront/Makefile index 5d1707dd7..182ef6531 100644 --- a/drivers/xen/blkfront/Makefile +++ b/drivers/xen/blkfront/Makefile @@ -1,3 +1,5 @@ -obj-y := blkfront.o vbd.o +obj-$(CONFIG_XEN_BLKDEV_FRONTEND) := xenblk.o + +xenblk-objs := blkfront.o vbd.o diff --git a/drivers/xen/blkfront/blkfront.c b/drivers/xen/blkfront/blkfront.c index 311b8398e..a911c766a 100644 --- a/drivers/xen/blkfront/blkfront.c +++ b/drivers/xen/blkfront/blkfront.c @@ -8,9 +8,13 @@ * Copyright (c) 2004, Christian Limpach * Copyright (c) 2004, Andrew Warfield * Copyright (c) 2005, Christopher Clark + * Copyright (c) 2005, XenSource Ltd * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without @@ -31,1450 +35,807 @@ * IN THE SOFTWARE. */ -#if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) -#endif - #include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include "block.h" -#else -#include "common.h" -#include -#include -#endif - #include #include #include #include -#include -#include -#ifdef CONFIG_XEN_BLKDEV_GRANT -#include -#include -#endif - -typedef unsigned char byte; /* from linux/ide.h */ +#include +#include +#include +#include +#include -/* Control whether runtime update of vbds is enabled. */ -#define ENABLE_VBD_UPDATE 1 +#define BLKIF_STATE_DISCONNECTED 0 +#define BLKIF_STATE_CONNECTED 1 +#define BLKIF_STATE_SUSPENDED 2 -#if ENABLE_VBD_UPDATE -static void vbd_update(void); -#else -static void vbd_update(void){}; -#endif +#define MAXIMUM_OUTSTANDING_BLOCK_REQS \ + (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE) +#define GRANT_INVALID_REF 0 -#define BLKIF_STATE_CLOSED 0 -#define BLKIF_STATE_DISCONNECTED 1 -#define BLKIF_STATE_CONNECTED 2 +static void connect(struct blkfront_info *); +static void blkfront_closing(struct xenbus_device *); +static int blkfront_remove(struct xenbus_device *); +static int talk_to_backend(struct xenbus_device *, struct blkfront_info *); +static int setup_blkring(struct xenbus_device *, struct blkfront_info *); -#define WPRINTK(fmt, args...) printk(KERN_WARNING "xen_blk: " fmt, ##args) +static void kick_pending_request_queues(struct blkfront_info *); -static int blkif_handle = 0; -static unsigned int blkif_state = BLKIF_STATE_CLOSED; -static unsigned int blkif_evtchn = 0; -static unsigned int blkif_irq = 0; +static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs); +static void blkif_restart_queue(void *arg); +static void blkif_recover(struct blkfront_info *); +static void blkif_completion(struct blk_shadow *); +static void blkif_free(struct blkfront_info *, int); -static int blkif_control_rsp_valid; -static blkif_response_t blkif_control_rsp; -static blkif_front_ring_t blk_ring; +/** + * Entry point to this code when a new device is created. Allocate the basic + * structures and the ring buffer for communication with the backend, and + * inform the backend of the appropriate details for those. Switch to + * Initialised state. + */ +static int blkfront_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + int err, vdevice, i; + struct blkfront_info *info; + + /* FIXME: Use dynamic device id if this is not set. */ + err = xenbus_scanf(XBT_NIL, dev->nodename, + "virtual-device", "%i", &vdevice); + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading virtual-device"); + return err; + } + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); + return -ENOMEM; + } + + info->xbdev = dev; + info->vdevice = vdevice; + info->connected = BLKIF_STATE_DISCONNECTED; + INIT_WORK(&info->work, blkif_restart_queue, (void *)info); + + for (i = 0; i < BLK_RING_SIZE; i++) + info->shadow[i].req.id = i+1; + info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + + /* Front end dir is a number, which is used as the id. */ + info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0); + dev->dev.driver_data = info; + + err = talk_to_backend(dev, info); + if (err) { + kfree(info); + dev->dev.driver_data = NULL; + return err; + } + + return 0; +} + + +/** + * We are reconnecting to the backend, due to a suspend/resume, or a backend + * driver restart. We tear down our blkif structure and recreate it, but + * leave the device-layer structures intact so that this is transparent to the + * rest of the kernel. + */ +static int blkfront_resume(struct xenbus_device *dev) +{ + struct blkfront_info *info = dev->dev.driver_data; + int err; + + DPRINTK("blkfront_resume: %s\n", dev->nodename); + + blkif_free(info, 1); + + err = talk_to_backend(dev, info); + if (!err) + blkif_recover(info); + + return err; +} + + +/* Common code used when first setting up, and when resuming. */ +static int talk_to_backend(struct xenbus_device *dev, + struct blkfront_info *info) +{ + const char *message = NULL; + struct xenbus_transaction xbt; + int err; + + /* Create shared ring, alloc event channel. */ + err = setup_blkring(dev, info); + if (err) + goto out; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + goto destroy_blkring; + } + + err = xenbus_printf(xbt, dev->nodename, + "ring-ref","%u", info->ring_ref); + if (err) { + message = "writing ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(xbt, dev->nodename, + "event-channel", "%u", info->evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + + err = xenbus_transaction_end(xbt, 0); + if (err) { + if (err == -EAGAIN) + goto again; + xenbus_dev_fatal(dev, err, "completing transaction"); + goto destroy_blkring; + } + + xenbus_switch_state(dev, XenbusStateInitialised); + + return 0; + + abort_transaction: + xenbus_transaction_end(xbt, 1); + if (message) + xenbus_dev_fatal(dev, err, "%s", message); + destroy_blkring: + blkif_free(info, 0); + out: + return err; +} -#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) -#ifdef CONFIG_XEN_BLKDEV_GRANT -static domid_t rdomid = 0; -static grant_ref_t gref_head, gref_terminal; -#define MAXIMUM_OUTSTANDING_BLOCK_REQS \ - (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) -#define GRANTREF_INVALID (1<<15) -#endif +static int setup_blkring(struct xenbus_device *dev, + struct blkfront_info *info) +{ + blkif_sring_t *sring; + int err; -static struct blk_shadow { - blkif_request_t req; - unsigned long request; - unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -} blk_shadow[BLK_RING_SIZE]; -unsigned long blk_shadow_free; + info->ring_ref = GRANT_INVALID_REF; -static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */ + sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL); + if (!sring) { + xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); + return -ENOMEM; + } + SHARED_RING_INIT(sring); + FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); -static void kick_pending_request_queues(void); + err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); + if (err < 0) { + free_page((unsigned long)sring); + info->ring.sring = NULL; + goto fail; + } + info->ring_ref = err; -int __init xlblk_init(void); + err = xenbus_alloc_evtchn(dev, &info->evtchn); + if (err) + goto fail; -static void blkif_completion(struct blk_shadow *s); + err = bind_evtchn_to_irqhandler( + info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); + if (err <= 0) { + xenbus_dev_fatal(dev, err, + "bind_evtchn_to_irqhandler failed"); + goto fail; + } + info->irq = err; -static inline int GET_ID_FROM_FREELIST(void) -{ - unsigned long free = blk_shadow_free; - BUG_ON(free > BLK_RING_SIZE); - blk_shadow_free = blk_shadow[free].req.id; - blk_shadow[free].req.id = 0x0fffffee; /* debug */ - return free; + return 0; +fail: + blkif_free(info, 0); + return err; } -static inline void ADD_ID_TO_FREELIST(unsigned long id) + +/** + * Callback received when the backend's state changes. + */ +static void backend_changed(struct xenbus_device *dev, + enum xenbus_state backend_state) { - blk_shadow[id].req.id = blk_shadow_free; - blk_shadow[id].request = 0; - blk_shadow_free = id; -} + struct blkfront_info *info = dev->dev.driver_data; + struct block_device *bd; + DPRINTK("blkfront:backend_changed.\n"); -/************************ COMMON CODE (inlined) ************************/ + switch (backend_state) { + case XenbusStateUnknown: + case XenbusStateInitialising: + case XenbusStateInitWait: + case XenbusStateInitialised: + case XenbusStateClosed: + break; -/* Kernel-specific definitions used in the common code */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define DISABLE_SCATTERGATHER() -#else -static int sg_operation = -1; -#define DISABLE_SCATTERGATHER() (sg_operation = -1) -#endif + case XenbusStateConnected: + connect(info); + break; -static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r) -{ -#ifndef CONFIG_XEN_BLKDEV_GRANT - int i; -#endif + case XenbusStateClosing: + bd = bdget(info->dev); + if (bd == NULL) + xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); - s->req = *r; - -#ifndef CONFIG_XEN_BLKDEV_GRANT - for ( i = 0; i < r->nr_segments; i++ ) - s->req.frame_and_sects[i] = machine_to_phys(r->frame_and_sects[i]); -#endif + mutex_lock(&bd->bd_mutex); + if (info->users > 0) + xenbus_dev_error(dev, -EBUSY, + "Device in use; refusing to close"); + else + blkfront_closing(dev); + mutex_unlock(&bd->bd_mutex); + bdput(bd); + break; + } } -static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s) -{ -#ifndef CONFIG_XEN_BLKDEV_GRANT - int i; -#endif - - *r = s->req; -#ifndef CONFIG_XEN_BLKDEV_GRANT - for ( i = 0; i < s->req.nr_segments; i++ ) - r->frame_and_sects[i] = phys_to_machine(s->req.frame_and_sects[i]); -#endif -} +/* ** Connection ** */ -static inline void flush_requests(void) +/* + * Invoked when the backend is finally 'ready' (and has told produced + * the details about the physical device - #sectors, size, etc). + */ +static void connect(struct blkfront_info *info) +{ + unsigned long sectors, sector_size; + unsigned int binfo; + int err; + + if ((info->connected == BLKIF_STATE_CONNECTED) || + (info->connected == BLKIF_STATE_SUSPENDED) ) + return; + + DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend); + + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, + "sectors", "%lu", §ors, + "info", "%u", &binfo, + "sector-size", "%lu", §or_size, + NULL); + if (err) { + xenbus_dev_fatal(info->xbdev, err, + "reading backend fields at %s", + info->xbdev->otherend); + return; + } + + err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); + if (err) { + xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", + info->xbdev->otherend); + return; + } + + (void)xenbus_switch_state(info->xbdev, XenbusStateConnected); + + /* Kick pending requests. */ + spin_lock_irq(&blkif_io_lock); + info->connected = BLKIF_STATE_CONNECTED; + kick_pending_request_queues(info); + spin_unlock_irq(&blkif_io_lock); + + add_disk(info->gd); +} + +/** + * Handle the change of state of the backend to Closing. We must delete our + * device-layer structures now, to ensure that writes are flushed through to + * the backend. Once is this done, we can switch to Closed in + * acknowledgement. + */ +static void blkfront_closing(struct xenbus_device *dev) { - DISABLE_SCATTERGATHER(); - RING_PUSH_REQUESTS(&blk_ring); - notify_via_evtchn(blkif_evtchn); -} + struct blkfront_info *info = dev->dev.driver_data; + unsigned long flags; + DPRINTK("blkfront_closing: %s removed\n", dev->nodename); -/************************** KERNEL VERSION 2.6 **************************/ + if (info->rq == NULL) + return; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + spin_lock_irqsave(&blkif_io_lock, flags); + /* No more blkif_request(). */ + blk_stop_queue(info->rq); + /* No more gnttab callback work. */ + gnttab_cancel_free_callback(&info->callback); + flush_scheduled_work(); + spin_unlock_irqrestore(&blkif_io_lock, flags); -module_init(xlblk_init); + xlvbd_del(info); -#if ENABLE_VBD_UPDATE -static void update_vbds_task(void *unused) -{ - xlvbd_update_vbds(); + xenbus_switch_state(dev, XenbusStateClosed); } -static void vbd_update(void) -{ - static DECLARE_WORK(update_tq, update_vbds_task, NULL); - schedule_work(&update_tq); -} -#endif /* ENABLE_VBD_UPDATE */ -static void kick_pending_request_queues(void) +static int blkfront_remove(struct xenbus_device *dev) { - if ( (xlbd_blk_queue != NULL) && - test_bit(QUEUE_FLAG_STOPPED, &xlbd_blk_queue->queue_flags) ) - { - blk_start_queue(xlbd_blk_queue); - /* XXXcl call to request_fn should not be needed but - * we get stuck without... needs investigating - */ - xlbd_blk_queue->request_fn(xlbd_blk_queue); - } -} + struct blkfront_info *info = dev->dev.driver_data; + DPRINTK("blkfront_remove: %s removed\n", dev->nodename); -int blkif_open(struct inode *inode, struct file *filep) -{ - struct gendisk *gd = inode->i_bdev->bd_disk; - struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data; + blkif_free(info, 0); - /* Update of usage count is protected by per-device semaphore. */ - di->mi->usage++; - - return 0; -} + kfree(info); - -int blkif_release(struct inode *inode, struct file *filep) -{ - struct gendisk *gd = inode->i_bdev->bd_disk; - struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data; - - /* - * When usage drops to zero it may allow more VBD updates to occur. - * Update of usage count is protected by a per-device semaphore. - */ - if ( --di->mi->usage == 0 ) - vbd_update(); - - return 0; + return 0; } -int blkif_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument) +static inline int GET_ID_FROM_FREELIST( + struct blkfront_info *info) { - int i; - - DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", - command, (long)argument, inode->i_rdev); - - switch ( command ) - { - case HDIO_GETGEO: - /* return ENOSYS to use defaults */ - return -ENOSYS; - - case CDROMMULTISESSION: - DPRINTK("FIXME: support multisession CDs later\n"); - for ( i = 0; i < sizeof(struct cdrom_multisession); i++ ) - if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT; - return 0; - - default: - printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", - command); - return -ENOSYS; - } - - return 0; + unsigned long free = info->shadow_free; + BUG_ON(free > BLK_RING_SIZE); + info->shadow_free = info->shadow[free].req.id; + info->shadow[free].req.id = 0x0fffffee; /* debug */ + return free; } - -/* - * blkif_queue_request - * - * request block io - * - * id: for guest use only. - * operation: BLKIF_OP_{READ,WRITE,PROBE} - * buffer: buffer to read/write into. this should be a - * virtual address in the guest os. - */ -static int blkif_queue_request(struct request *req) +static inline void ADD_ID_TO_FREELIST( + struct blkfront_info *info, unsigned long id) { - struct xlbd_disk_info *di = - (struct xlbd_disk_info *)req->rq_disk->private_data; - unsigned long buffer_ma; - blkif_request_t *ring_req; - struct bio *bio; - struct bio_vec *bvec; - int idx; - unsigned long id; - unsigned int fsect, lsect; -#ifdef CONFIG_XEN_BLKDEV_GRANT - int ref; -#endif - - if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) ) - return 1; - - /* Fill out a communications ring structure. */ - ring_req = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt); - id = GET_ID_FROM_FREELIST(); - blk_shadow[id].request = (unsigned long)req; - - ring_req->id = id; - ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : - BLKIF_OP_READ; - ring_req->sector_number = (blkif_sector_t)req->sector; - ring_req->device = di->xd_device; - - ring_req->nr_segments = 0; - rq_for_each_bio(bio, req) - { - bio_for_each_segment(bvec, bio, idx) - { - if ( ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST ) - BUG(); - buffer_ma = page_to_phys(bvec->bv_page); - fsect = bvec->bv_offset >> 9; - lsect = fsect + (bvec->bv_len >> 9) - 1; -#ifdef CONFIG_XEN_BLKDEV_GRANT - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); - ASSERT( ref != -ENOSPC ); - - gnttab_grant_foreign_access_ref( - ref, - rdomid, - buffer_ma >> PAGE_SHIFT, - rq_data_dir(req) ); - - blk_shadow[id].frame[ring_req->nr_segments] = - buffer_ma >> PAGE_SHIFT; - - ring_req->frame_and_sects[ring_req->nr_segments++] = - (((u32) ref) << 16) | (fsect << 3) | lsect; - -#else - ring_req->frame_and_sects[ring_req->nr_segments++] = - buffer_ma | (fsect << 3) | lsect; -#endif - } - } - - blk_ring.req_prod_pvt++; - - /* Keep a private copy so we can reissue requests when recovering. */ - pickle_request(&blk_shadow[id], ring_req); - - return 0; + info->shadow[id].req.id = info->shadow_free; + info->shadow[id].request = 0; + info->shadow_free = id; } - -/* - * do_blkif_request - * read a block; request is in a request queue - */ -void do_blkif_request(request_queue_t *rq) +static inline void flush_requests(struct blkfront_info *info) { - struct request *req; - int queued; - - DPRINTK("Entered do_blkif_request\n"); - - queued = 0; - - while ( (req = elv_next_request(rq)) != NULL ) - { - if ( !blk_fs_request(req) ) - { - end_request(req, 0); - continue; - } - - if ( RING_FULL(&blk_ring) ) - { - blk_stop_queue(rq); - break; - } - - DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n", - req, req->cmd, req->sector, req->current_nr_sectors, - req->nr_sectors, req->buffer, - rq_data_dir(req) ? "write" : "read"); - - blkdev_dequeue_request(req); - if ( blkif_queue_request(req) ) - { - blk_stop_queue(rq); - break; - } - - queued++; - } - - if ( queued != 0 ) - flush_requests(); -} + int notify; + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify); -static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) -{ - struct request *req; - blkif_response_t *bret; - RING_IDX i, rp; - unsigned long flags; - - spin_lock_irqsave(&blkif_io_lock, flags); - - if ( unlikely(blkif_state == BLKIF_STATE_CLOSED) || - unlikely(recovery) ) - { - spin_unlock_irqrestore(&blkif_io_lock, flags); - return IRQ_HANDLED; - } - - rp = blk_ring.sring->rsp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ - - for ( i = blk_ring.rsp_cons; i != rp; i++ ) - { - unsigned long id; - - bret = RING_GET_RESPONSE(&blk_ring, i); - id = bret->id; - req = (struct request *)blk_shadow[id].request; - - blkif_completion(&blk_shadow[id]); - - ADD_ID_TO_FREELIST(id); - - switch ( bret->operation ) - { - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - if ( unlikely(bret->status != BLKIF_RSP_OKAY) ) - DPRINTK("Bad return from blkdev data request: %x\n", - bret->status); - - if ( unlikely(end_that_request_first - (req, - (bret->status == BLKIF_RSP_OKAY), - req->hard_nr_sectors)) ) - BUG(); - end_that_request_last(req); - - break; - case BLKIF_OP_PROBE: - memcpy(&blkif_control_rsp, bret, sizeof(*bret)); - blkif_control_rsp_valid = 1; - break; - default: - BUG(); - } - } - - blk_ring.rsp_cons = i; - - kick_pending_request_queues(); - - spin_unlock_irqrestore(&blkif_io_lock, flags); - - return IRQ_HANDLED; + if (notify) + notify_remote_via_irq(info->irq); } -#else -/************************** KERNEL VERSION 2.4 **************************/ - -static kdev_t sg_dev; -static unsigned long sg_next_sect; - -/* - * Request queues with outstanding work, but ring is currently full. - * We need no special lock here, as we always access this with the - * blkif_io_lock held. We only need a small maximum list. - */ -#define MAX_PENDING 8 -static request_queue_t *pending_queues[MAX_PENDING]; -static int nr_pending; - - -#define blkif_io_lock io_request_lock - -/*============================================================================*/ -#if ENABLE_VBD_UPDATE - -/* - * blkif_update_int/update-vbds_task - handle VBD update events. - * Schedule a task for keventd to run, which will update the VBDs and perform - * the corresponding updates to our view of VBD state. - */ -static void update_vbds_task(void *unused) -{ - xlvbd_update_vbds(); +static void kick_pending_request_queues(struct blkfront_info *info) +{ + if (!RING_FULL(&info->ring)) { + /* Re-enable calldowns. */ + blk_start_queue(info->rq); + /* Kick things off immediately. */ + do_blkif_request(info->rq); + } } -static void vbd_update(void) +static void blkif_restart_queue(void *arg) { - static struct tq_struct update_tq; - update_tq.routine = update_vbds_task; - schedule_task(&update_tq); + struct blkfront_info *info = (struct blkfront_info *)arg; + spin_lock_irq(&blkif_io_lock); + if (info->connected == BLKIF_STATE_CONNECTED) + kick_pending_request_queues(info); + spin_unlock_irq(&blkif_io_lock); } -#endif /* ENABLE_VBD_UPDATE */ -/*============================================================================*/ - -static void kick_pending_request_queues(void) +static void blkif_restart_queue_callback(void *arg) { - /* We kick pending request queues if the ring is reasonably empty. */ - if ( (nr_pending != 0) && - (RING_PENDING_REQUESTS(&blk_ring) < (BLK_RING_SIZE >> 1)) ) - { - /* Attempt to drain the queue, but bail if the ring becomes full. */ - while ( (nr_pending != 0) && !RING_FULL(&blk_ring) ) - do_blkif_request(pending_queues[--nr_pending]); - } + struct blkfront_info *info = (struct blkfront_info *)arg; + schedule_work(&info->work); } int blkif_open(struct inode *inode, struct file *filep) { - short xldev = inode->i_rdev; - struct gendisk *gd = get_gendisk(xldev); - xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); - short minor = MINOR(xldev); - - if ( gd->part[minor].nr_sects == 0 ) - { - /* - * Device either doesn't exist, or has zero capacity; we use a few - * cheesy heuristics to return the relevant error code - */ - if ( (gd->sizes[minor >> gd->minor_shift] != 0) || - ((minor & (gd->max_p - 1)) != 0) ) - { - /* - * We have a real device, but no such partition, or we just have a - * partition number so guess this is the problem. - */ - return -ENXIO; /* no such device or address */ - } - else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE ) - { - /* This is a removable device => assume that media is missing. */ - return -ENOMEDIUM; /* media not present (this is a guess) */ - } - else - { - /* Just go for the general 'no such device' error. */ - return -ENODEV; /* no such device */ - } - } - - /* Update of usage count is protected by per-device semaphore. */ - disk->usage++; - - return 0; + struct blkfront_info *info = inode->i_bdev->bd_disk->private_data; + info->users++; + return 0; } int blkif_release(struct inode *inode, struct file *filep) { - xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); + struct blkfront_info *info = inode->i_bdev->bd_disk->private_data; + info->users--; + if (info->users == 0) { + /* Check whether we have been instructed to close. We will + have ignored this request initially, as the device was + still mounted. */ + struct xenbus_device * dev = info->xbdev; + enum xenbus_state state = xenbus_read_driver_state(dev->otherend); - /* - * When usage drops to zero it may allow more VBD updates to occur. - * Update of usage count is protected by a per-device semaphore. - */ - if ( --disk->usage == 0 ) { - vbd_update(); - } - - return 0; + if (state == XenbusStateClosing) + blkfront_closing(dev); + } + return 0; } int blkif_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument) + unsigned command, unsigned long argument) { - kdev_t dev = inode->i_rdev; - struct hd_geometry *geo = (struct hd_geometry *)argument; - struct gendisk *gd; - struct hd_struct *part; - int i; - unsigned short cylinders; - byte heads, sectors; - - /* NB. No need to check permissions. That is done for us. */ - - DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", - command, (long) argument, dev); - - gd = get_gendisk(dev); - part = &gd->part[MINOR(dev)]; - - switch ( command ) - { - case BLKGETSIZE: - DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); - return put_user(part->nr_sects, (unsigned long *) argument); - - case BLKGETSIZE64: - DPRINTK_IOCTL(" BLKGETSIZE64: %x %llx\n", BLKGETSIZE64, - (u64)part->nr_sects * 512); - return put_user((u64)part->nr_sects * 512, (u64 *) argument); - - case BLKRRPART: /* re-read partition table */ - DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); - return blkif_revalidate(dev); - - case BLKSSZGET: - return hardsect_size[MAJOR(dev)][MINOR(dev)]; - - case BLKBSZGET: /* get block size */ - DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET); - break; - - case BLKBSZSET: /* set block size */ - DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET); - break; - - case BLKRASET: /* set read-ahead */ - DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET); - break; - - case BLKRAGET: /* get read-ahead */ - DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET); - break; - - case HDIO_GETGEO: - DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO); - if (!argument) return -EINVAL; - - /* We don't have real geometry info, but let's at least return - values consistent with the size of the device */ - - heads = 0xff; - sectors = 0x3f; - cylinders = part->nr_sects / (heads * sectors); - - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(heads, (byte *)&geo->heads)) return -EFAULT; - if (put_user(sectors, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(cylinders, (unsigned short *)&geo->cylinders)) return -EFAULT; - - return 0; - - case HDIO_GETGEO_BIG: - DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); - if (!argument) return -EINVAL; - - /* We don't have real geometry info, but let's at least return - values consistent with the size of the device */ - - heads = 0xff; - sectors = 0x3f; - cylinders = part->nr_sects / (heads * sectors); - - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(heads, (byte *)&geo->heads)) return -EFAULT; - if (put_user(sectors, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(cylinders, (unsigned int *) &geo->cylinders)) return -EFAULT; - - return 0; - - case CDROMMULTISESSION: - DPRINTK("FIXME: support multisession CDs later\n"); - for ( i = 0; i < sizeof(struct cdrom_multisession); i++ ) - if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT; - return 0; - - case SCSI_IOCTL_GET_BUS_NUMBER: - DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in XL blkif"); - return -ENOSYS; - - default: - printk(KERN_ALERT "ioctl %08x not supported by XL blkif\n", command); - return -ENOSYS; - } - - return 0; -} + int i; + DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", + command, (long)argument, inode->i_rdev); + switch (command) { + case CDROMMULTISESSION: + DPRINTK("FIXME: support multisession CDs later\n"); + for (i = 0; i < sizeof(struct cdrom_multisession); i++) + if (put_user(0, (char __user *)(argument + i))) + return -EFAULT; + return 0; -/* check media change: should probably do something here in some cases :-) */ -int blkif_check(kdev_t dev) -{ - DPRINTK("blkif_check\n"); - return 0; + default: + /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", + command);*/ + return -EINVAL; /* same return as native Linux */ + } + + return 0; } -int blkif_revalidate(kdev_t dev) + +int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg) { - struct block_device *bd; - struct gendisk *gd; - xl_disk_t *disk; - unsigned long capacity; - int i, rc = 0; - - if ( (bd = bdget(dev)) == NULL ) - return -EINVAL; - - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ - down(&bd->bd_sem); - - if ( ((gd = get_gendisk(dev)) == NULL) || - ((disk = xldev_to_xldisk(dev)) == NULL) || - ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) ) - { - rc = -EINVAL; - goto out; - } - - if ( disk->usage > 1 ) - { - rc = -EBUSY; - goto out; - } - - /* Only reread partition table if VBDs aren't mapped to partitions. */ - if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) ) - { - for ( i = gd->max_p - 1; i >= 0; i-- ) - { - invalidate_device(dev+i, 1); - gd->part[MINOR(dev+i)].start_sect = 0; - gd->part[MINOR(dev+i)].nr_sects = 0; - gd->sizes[MINOR(dev+i)] = 0; - } - - grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity); - } + /* We don't have real geometry info, but let's at least return + values consistent with the size of the device */ + sector_t nsect = get_capacity(bd->bd_disk); + sector_t cylinders = nsect; - out: - up(&bd->bd_sem); - bdput(bd); - return rc; + hg->heads = 0xff; + hg->sectors = 0x3f; + sector_div(cylinders, hg->heads * hg->sectors); + hg->cylinders = cylinders; + if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect) + hg->cylinders = 0xffff; + return 0; } /* * blkif_queue_request * - * request block io - * + * request block io + * * id: for guest use only. * operation: BLKIF_OP_{READ,WRITE,PROBE} * buffer: buffer to read/write into. this should be a * virtual address in the guest os. */ -static int blkif_queue_request(unsigned long id, - int operation, - char * buffer, - unsigned long sector_number, - unsigned short nr_sectors, - kdev_t device) +static int blkif_queue_request(struct request *req) { - unsigned long buffer_ma = virt_to_bus(buffer); - unsigned long xid; - struct gendisk *gd; - blkif_request_t *req; - struct buffer_head *bh; - unsigned int fsect, lsect; -#ifdef CONFIG_XEN_BLKDEV_GRANT - int ref; -#endif - - fsect = (buffer_ma & ~PAGE_MASK) >> 9; - lsect = fsect + nr_sectors - 1; - - /* Buffer must be sector-aligned. Extent mustn't cross a page boundary. */ - if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) ) - BUG(); - if ( lsect > 7 ) - BUG(); - - buffer_ma &= PAGE_MASK; - - if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) ) - return 1; - - switch ( operation ) - { - - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - gd = get_gendisk(device); - - /* - * Update the sector_number we'll pass down as appropriate; note that - * we could sanity check that resulting sector will be in this - * partition, but this will happen in driver backend anyhow. - */ - sector_number += gd->part[MINOR(device)].start_sect; - - /* - * If this unit doesn't consist of virtual partitions then we clear - * the partn bits from the device number. - */ - if ( !(gd->flags[MINOR(device)>>gd->minor_shift] & - GENHD_FL_VIRT_PARTNS) ) - device &= ~(gd->max_p - 1); - - if ( (sg_operation == operation) && - (sg_dev == device) && - (sg_next_sect == sector_number) ) - { - req = RING_GET_REQUEST(&blk_ring, - blk_ring.req_prod_pvt - 1); - bh = (struct buffer_head *)id; - - bh->b_reqnext = (struct buffer_head *)blk_shadow[req->id].request; - blk_shadow[req->id].request = (unsigned long)id; - -#ifdef CONFIG_XEN_BLKDEV_GRANT - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); - ASSERT( ref != -ENOSPC ); - - gnttab_grant_foreign_access_ref( - ref, - rdomid, - buffer_ma >> PAGE_SHIFT, - ( operation == BLKIF_OP_WRITE ? 1 : 0 ) ); - - blk_shadow[id].frame[req->nr_segments] = - buffer_ma >> PAGE_SHIFT; - - req->frame_and_sects[req->nr_segments] = - (((u32) ref ) << 16) | (fsect << 3) | lsect; -#else - req->frame_and_sects[req->nr_segments] = - buffer_ma | (fsect << 3) | lsect; -#endif - if ( ++req->nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST ) - sg_next_sect += nr_sectors; - else - DISABLE_SCATTERGATHER(); - - /* Update the copy of the request in the recovery ring. */ - pickle_request(&blk_shadow[req->id], req ); - - return 0; - } - else if ( RING_FULL(&blk_ring) ) - { - return 1; - } - else - { - sg_operation = operation; - sg_dev = device; - sg_next_sect = sector_number + nr_sectors; - } - break; - - default: - panic("unknown op %d\n", operation); - } - - /* Fill out a communications ring structure. */ - req = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt); - - xid = GET_ID_FROM_FREELIST(); - blk_shadow[xid].request = (unsigned long)id; - - req->id = xid; - req->operation = operation; - req->sector_number = (blkif_sector_t)sector_number; - req->device = device; - req->nr_segments = 1; -#ifdef CONFIG_XEN_BLKDEV_GRANT - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); - ASSERT( ref != -ENOSPC ); - - gnttab_grant_foreign_access_ref( - ref, - rdomid, - buffer_ma >> PAGE_SHIFT, - ( operation == BLKIF_OP_WRITE ? 1 : 0 ) ); - - blk_shadow[xid].frame[0] = buffer_ma >> PAGE_SHIFT; - - req->frame_and_sects[0] = (((u32) ref)<<16) | (fsect<<3) | lsect; -#else - req->frame_and_sects[0] = buffer_ma | (fsect<<3) | lsect; -#endif - - /* Keep a private copy so we can reissue requests when recovering. */ - pickle_request(&blk_shadow[xid], req); - - blk_ring.req_prod_pvt++; - - return 0; + struct blkfront_info *info = req->rq_disk->private_data; + unsigned long buffer_mfn; + blkif_request_t *ring_req; + struct bio *bio; + struct bio_vec *bvec; + int idx; + unsigned long id; + unsigned int fsect, lsect; + int ref; + grant_ref_t gref_head; + + if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) + return 1; + + if (gnttab_alloc_grant_references( + BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) { + gnttab_request_free_callback( + &info->callback, + blkif_restart_queue_callback, + info, + BLKIF_MAX_SEGMENTS_PER_REQUEST); + return 1; + } + + /* Fill out a communications ring structure. */ + ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt); + id = GET_ID_FROM_FREELIST(info); + info->shadow[id].request = (unsigned long)req; + + ring_req->id = id; + ring_req->operation = rq_data_dir(req) ? + BLKIF_OP_WRITE : BLKIF_OP_READ; + ring_req->sector_number = (blkif_sector_t)req->sector; + ring_req->handle = info->handle; + + ring_req->nr_segments = 0; + rq_for_each_bio (bio, req) { + bio_for_each_segment (bvec, bio, idx) { + BUG_ON(ring_req->nr_segments + == BLKIF_MAX_SEGMENTS_PER_REQUEST); + buffer_mfn = page_to_phys(bvec->bv_page) >> PAGE_SHIFT; + fsect = bvec->bv_offset >> 9; + lsect = fsect + (bvec->bv_len >> 9) - 1; + /* install a grant reference. */ + ref = gnttab_claim_grant_reference(&gref_head); + BUG_ON(ref == -ENOSPC); + + gnttab_grant_foreign_access_ref( + ref, + info->xbdev->otherend_id, + buffer_mfn, + rq_data_dir(req) ); + + info->shadow[id].frame[ring_req->nr_segments] = + mfn_to_pfn(buffer_mfn); + + ring_req->seg[ring_req->nr_segments] = + (struct blkif_request_segment) { + .gref = ref, + .first_sect = fsect, + .last_sect = lsect }; + + ring_req->nr_segments++; + } + } + + info->ring.req_prod_pvt++; + + /* Keep a private copy so we can reissue requests when recovering. */ + info->shadow[id].req = *ring_req; + + gnttab_free_grant_references(gref_head); + + return 0; } - /* * do_blkif_request * read a block; request is in a request queue */ void do_blkif_request(request_queue_t *rq) { - struct request *req; - struct buffer_head *bh, *next_bh; - int rw, nsect, full, queued = 0; - - DPRINTK("Entered do_blkif_request\n"); - - while ( !rq->plugged && !list_empty(&rq->queue_head)) - { - if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) - goto out; - - DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n", - req, req->cmd, req->sector, - req->current_nr_sectors, req->nr_sectors, req->bh); - - rw = req->cmd; - if ( rw == READA ) - rw = READ; - if ( unlikely((rw != READ) && (rw != WRITE)) ) - panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw); - - req->errors = 0; - - bh = req->bh; - while ( bh != NULL ) - { - next_bh = bh->b_reqnext; - bh->b_reqnext = NULL; - - full = blkif_queue_request( - (unsigned long)bh, - (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE, - bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev); - - if ( full ) - { - bh->b_reqnext = next_bh; - pending_queues[nr_pending++] = rq; - if ( unlikely(nr_pending >= MAX_PENDING) ) - BUG(); - goto out; - } - - queued++; - - /* Dequeue the buffer head from the request. */ - nsect = bh->b_size >> 9; - bh = req->bh = next_bh; - - if ( bh != NULL ) - { - /* There's another buffer head to do. Update the request. */ - req->hard_sector += nsect; - req->hard_nr_sectors -= nsect; - req->sector = req->hard_sector; - req->nr_sectors = req->hard_nr_sectors; - req->current_nr_sectors = bh->b_size >> 9; - req->buffer = bh->b_data; - } - else - { - /* That was the last buffer head. Finalise the request. */ - if ( unlikely(end_that_request_first(req, 1, "XenBlk")) ) - BUG(); - blkdev_dequeue_request(req); - end_that_request_last(req); - } - } - } + struct blkfront_info *info = NULL; + struct request *req; + int queued; - out: - if ( queued != 0 ) - flush_requests(); -} + DPRINTK("Entered do_blkif_request\n"); + queued = 0; -static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) -{ - RING_IDX i, rp; - unsigned long flags; - struct buffer_head *bh, *next_bh; - - spin_lock_irqsave(&io_request_lock, flags); - - if ( unlikely(blkif_state == BLKIF_STATE_CLOSED || recovery) ) - { - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - - rp = blk_ring.sring->rsp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ - - for ( i = blk_ring.rsp_cons; i != rp; i++ ) - { - unsigned long id; - blkif_response_t *bret; - - bret = RING_GET_RESPONSE(&blk_ring, i); - id = bret->id; - bh = (struct buffer_head *)blk_shadow[id].request; - - blkif_completion(&blk_shadow[id]); - - ADD_ID_TO_FREELIST(id); - - switch ( bret->operation ) - { - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - if ( unlikely(bret->status != BLKIF_RSP_OKAY) ) - DPRINTK("Bad return from blkdev data request: %lx\n", - bret->status); - for ( ; bh != NULL; bh = next_bh ) - { - next_bh = bh->b_reqnext; - bh->b_reqnext = NULL; - bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY); - } - - break; - case BLKIF_OP_PROBE: - memcpy(&blkif_control_rsp, bret, sizeof(*bret)); - blkif_control_rsp_valid = 1; - break; - default: - BUG(); - } - - } - blk_ring.rsp_cons = i; - - kick_pending_request_queues(); - - spin_unlock_irqrestore(&io_request_lock, flags); -} + while ((req = elv_next_request(rq)) != NULL) { + info = req->rq_disk->private_data; + if (!blk_fs_request(req)) { + end_request(req, 0); + continue; + } -#endif + if (RING_FULL(&info->ring)) + goto wait; -/***************************** COMMON CODE *******************************/ + DPRINTK("do_blk_req %p: cmd %p, sec %lx, " + "(%u/%li) buffer:%p [%s]\n", + req, req->cmd, req->sector, req->current_nr_sectors, + req->nr_sectors, req->buffer, + rq_data_dir(req) ? "write" : "read"); -#ifdef CONFIG_XEN_BLKDEV_GRANT -void blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp, - unsigned long address) -{ - int ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); - ASSERT( ref != -ENOSPC ); - gnttab_grant_foreign_access_ref( ref, rdomid, address >> PAGE_SHIFT, 0 ); + blkdev_dequeue_request(req); + if (blkif_queue_request(req)) { + blk_requeue_request(rq, req); + wait: + /* Avoid pointless unplugs. */ + blk_stop_queue(rq); + break; + } - req->frame_and_sects[0] = (((u32) ref) << 16) | 7; + queued++; + } - blkif_control_send(req, rsp); + if (queued != 0) + flush_requests(info); } -#endif -void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp) -{ - unsigned long flags, id; - blkif_request_t *req_d; - - retry: - while ( RING_FULL(&blk_ring) ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - spin_lock_irqsave(&blkif_io_lock, flags); - if ( RING_FULL(&blk_ring) ) - { - spin_unlock_irqrestore(&blkif_io_lock, flags); - goto retry; - } - - DISABLE_SCATTERGATHER(); - req_d = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt); - *req_d = *req; - - id = GET_ID_FROM_FREELIST(); - req_d->id = id; - blk_shadow[id].request = (unsigned long)req; - - pickle_request(&blk_shadow[id], req); - - blk_ring.req_prod_pvt++; - flush_requests(); - - spin_unlock_irqrestore(&blkif_io_lock, flags); - - while ( !blkif_control_rsp_valid ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - memcpy(rsp, &blkif_control_rsp, sizeof(*rsp)); - blkif_control_rsp_valid = 0; -} - -/* Send a driver status notification to the domain controller. */ -static void send_driver_status(int ok) +static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) { - ctrl_msg_t cmsg = { - .type = CMSG_BLKIF_FE, - .subtype = CMSG_BLKIF_FE_DRIVER_STATUS, - .length = sizeof(blkif_fe_driver_status_t), - }; - blkif_fe_driver_status_t *msg = (void*)cmsg.msg; - - msg->status = (ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN); - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} + struct request *req; + blkif_response_t *bret; + RING_IDX i, rp; + unsigned long flags; + struct blkfront_info *info = (struct blkfront_info *)dev_id; + + spin_lock_irqsave(&blkif_io_lock, flags); + + if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { + spin_unlock_irqrestore(&blkif_io_lock, flags); + return IRQ_HANDLED; + } + + again: + rp = info->ring.sring->rsp_prod; + rmb(); /* Ensure we see queued responses up to 'rp'. */ + + for (i = info->ring.rsp_cons; i != rp; i++) { + unsigned long id; + int ret; + + bret = RING_GET_RESPONSE(&info->ring, i); + id = bret->id; + req = (struct request *)info->shadow[id].request; + + blkif_completion(&info->shadow[id]); + + ADD_ID_TO_FREELIST(info, id); + + switch (bret->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + if (unlikely(bret->status != BLKIF_RSP_OKAY)) + DPRINTK("Bad return from blkdev data " + "request: %x\n", bret->status); + + ret = end_that_request_first( + req, (bret->status == BLKIF_RSP_OKAY), + req->hard_nr_sectors); + BUG_ON(ret); + end_that_request_last( + req, (bret->status == BLKIF_RSP_OKAY)); + break; + default: + BUG(); + } + } + + info->ring.rsp_cons = i; + + if (i != info->ring.req_prod_pvt) { + int more_to_do; + RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do); + if (more_to_do) + goto again; + } else + info->ring.sring->rsp_event = i + 1; + + kick_pending_request_queues(info); + + spin_unlock_irqrestore(&blkif_io_lock, flags); + + return IRQ_HANDLED; +} + +static void blkif_free(struct blkfront_info *info, int suspend) +{ + /* Prevent new requests being issued until we fix things up. */ + spin_lock_irq(&blkif_io_lock); + info->connected = suspend ? + BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED; + /* No more blkif_request(). */ + if (info->rq) + blk_stop_queue(info->rq); + /* No more gnttab callback work. */ + gnttab_cancel_free_callback(&info->callback); + flush_scheduled_work(); + spin_unlock_irq(&blkif_io_lock); + + /* Free resources associated with old device channel. */ + if (info->ring_ref != GRANT_INVALID_REF) { + gnttab_end_foreign_access(info->ring_ref, 0, + (unsigned long)info->ring.sring); + info->ring_ref = GRANT_INVALID_REF; + info->ring.sring = NULL; + } + if (info->irq) + unbind_from_irqhandler(info->irq, info); + info->evtchn = info->irq = 0; -/* Tell the controller to bring up the interface. */ -static void blkif_send_interface_connect(void) -{ - ctrl_msg_t cmsg = { - .type = CMSG_BLKIF_FE, - .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT, - .length = sizeof(blkif_fe_interface_connect_t), - }; - blkif_fe_interface_connect_t *msg = (void*)cmsg.msg; - - msg->handle = 0; - msg->shmem_frame = (virt_to_machine(blk_ring.sring) >> PAGE_SHIFT); - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); } -static void blkif_free(void) +static void blkif_completion(struct blk_shadow *s) { - /* Prevent new requests being issued until we fix things up. */ - spin_lock_irq(&blkif_io_lock); - recovery = 1; - blkif_state = BLKIF_STATE_DISCONNECTED; - spin_unlock_irq(&blkif_io_lock); - - /* Free resources associated with old device channel. */ - if ( blk_ring.sring != NULL ) - { - free_page((unsigned long)blk_ring.sring); - blk_ring.sring = NULL; - } - free_irq(blkif_irq, NULL); - blkif_irq = 0; - - unbind_evtchn_from_irq(blkif_evtchn); - blkif_evtchn = 0; + int i; + for (i = 0; i < s->req.nr_segments; i++) + gnttab_end_foreign_access(s->req.seg[i].gref, 0, 0UL); } -static void blkif_close(void) +static void blkif_recover(struct blkfront_info *info) { -} + int i; + blkif_request_t *req; + struct blk_shadow *copy; + int j; -/* Move from CLOSED to DISCONNECTED state. */ -static void blkif_disconnect(void) -{ - blkif_sring_t *sring; - - if ( blk_ring.sring != NULL ) - free_page((unsigned long)blk_ring.sring); - - sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL); - SHARED_RING_INIT(sring); - FRONT_RING_INIT(&blk_ring, sring, PAGE_SIZE); - blkif_state = BLKIF_STATE_DISCONNECTED; - blkif_send_interface_connect(); -} + /* Stage 1: Make a safe copy of the shadow state. */ + copy = kmalloc(sizeof(info->shadow), GFP_KERNEL | __GFP_NOFAIL); + memcpy(copy, info->shadow, sizeof(info->shadow)); -static void blkif_reset(void) -{ - blkif_free(); - blkif_disconnect(); -} + /* Stage 2: Set up free list. */ + memset(&info->shadow, 0, sizeof(info->shadow)); + for (i = 0; i < BLK_RING_SIZE; i++) + info->shadow[i].req.id = i+1; + info->shadow_free = info->ring.req_prod_pvt; + info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; -static void blkif_recover(void) -{ - int i; - blkif_request_t *req; - struct blk_shadow *copy; -#ifdef CONFIG_XEN_BLKDEV_GRANT - int j; -#endif - - /* Stage 1: Make a safe copy of the shadow state. */ - copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL); - BUG_ON(copy == NULL); - memcpy(copy, blk_shadow, sizeof(blk_shadow)); - - /* Stage 2: Set up free list. */ - memset(&blk_shadow, 0, sizeof(blk_shadow)); - for ( i = 0; i < BLK_RING_SIZE; i++ ) - blk_shadow[i].req.id = i+1; - blk_shadow_free = blk_ring.req_prod_pvt; - blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; - - /* Stage 3: Find pending requests and requeue them. */ - for ( i = 0; i < BLK_RING_SIZE; i++ ) - { - /* Not in use? */ - if ( copy[i].request == 0 ) - continue; - - /* Grab a request slot and unpickle shadow state into it. */ - req = RING_GET_REQUEST( - &blk_ring, blk_ring.req_prod_pvt); - unpickle_request(req, ©[i]); - - /* We get a new request id, and must reset the shadow state. */ - req->id = GET_ID_FROM_FREELIST(); - memcpy(&blk_shadow[req->id], ©[i], sizeof(copy[i])); - -#ifdef CONFIG_XEN_BLKDEV_GRANT - /* Rewrite any grant references invalidated by suspend/resume. */ - for ( j = 0; j < req->nr_segments; j++ ) - { - if ( req->frame_and_sects[j] & GRANTREF_INVALID ) - gnttab_grant_foreign_access_ref( - blkif_gref_from_fas(req->frame_and_sects[j]), - rdomid, - blk_shadow[req->id].frame[j], - rq_data_dir((struct request *) - blk_shadow[req->id].request)); - req->frame_and_sects[j] &= ~GRANTREF_INVALID; - } - blk_shadow[req->id].req = *req; -#endif - - blk_ring.req_prod_pvt++; - } - - kfree(copy); - - recovery = 0; - - /* blk_ring->req_prod will be set when we flush_requests().*/ - wmb(); - - /* Kicks things back into life. */ - flush_requests(); - - /* Now safe to left other people use the interface. */ - blkif_state = BLKIF_STATE_CONNECTED; -} + /* Stage 3: Find pending requests and requeue them. */ + for (i = 0; i < BLK_RING_SIZE; i++) { + /* Not in use? */ + if (copy[i].request == 0) + continue; -static void blkif_connect(blkif_fe_interface_status_t *status) -{ - int err = 0; - - blkif_evtchn = status->evtchn; - blkif_irq = bind_evtchn_to_irq(blkif_evtchn); -#ifdef CONFIG_XEN_BLKDEV_GRANT - rdomid = status->domid; -#endif - - err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL); - if ( err ) - { - printk(KERN_ALERT "xen_blk: request_irq failed (err=%d)\n", err); - return; - } - - if ( recovery ) - { - blkif_recover(); - } - else - { - /* Transition to connected in case we need to do - * a partition probe on a whole disk. */ - blkif_state = BLKIF_STATE_CONNECTED; - - /* Probe for discs attached to the interface. */ - xlvbd_init(); - } - - /* Kick pending requests. */ - spin_lock_irq(&blkif_io_lock); - kick_pending_request_queues(); - spin_unlock_irq(&blkif_io_lock); -} + /* Grab a request slot and copy shadow state into it. */ + req = RING_GET_REQUEST( + &info->ring, info->ring.req_prod_pvt); + *req = copy[i].req; -static void unexpected(blkif_fe_interface_status_t *status) -{ - DPRINTK(" Unexpected blkif status %u in state %u\n", - status->status, blkif_state); -} + /* We get a new request id, and must reset the shadow state. */ + req->id = GET_ID_FROM_FREELIST(info); + memcpy(&info->shadow[req->id], ©[i], sizeof(copy[i])); -static void blkif_status(blkif_fe_interface_status_t *status) -{ - if ( status->handle != blkif_handle ) - { - WPRINTK(" Invalid blkif: handle=%u\n", status->handle); - unexpected(status); - return; - } - - switch ( status->status ) - { - case BLKIF_INTERFACE_STATUS_CLOSED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - unexpected(status); - break; - case BLKIF_STATE_DISCONNECTED: - case BLKIF_STATE_CONNECTED: - unexpected(status); - blkif_close(); - break; - } - break; - - case BLKIF_INTERFACE_STATUS_DISCONNECTED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - blkif_disconnect(); - break; - case BLKIF_STATE_DISCONNECTED: - case BLKIF_STATE_CONNECTED: - /* unexpected(status); */ /* occurs during suspend/resume */ - blkif_reset(); - break; - } - break; - - case BLKIF_INTERFACE_STATUS_CONNECTED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - unexpected(status); - blkif_disconnect(); - blkif_connect(status); - break; - case BLKIF_STATE_DISCONNECTED: - blkif_connect(status); - break; - case BLKIF_STATE_CONNECTED: - unexpected(status); - blkif_connect(status); - break; - } - break; - - case BLKIF_INTERFACE_STATUS_CHANGED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - case BLKIF_STATE_DISCONNECTED: - unexpected(status); - break; - case BLKIF_STATE_CONNECTED: - vbd_update(); - break; - } - break; - - default: - WPRINTK(" Invalid blkif status: %d\n", status->status); - break; - } -} + /* Rewrite any grant references invalidated by susp/resume. */ + for (j = 0; j < req->nr_segments; j++) + gnttab_grant_foreign_access_ref( + req->seg[j].gref, + info->xbdev->otherend_id, + pfn_to_mfn(info->shadow[req->id].frame[j]), + rq_data_dir( + (struct request *) + info->shadow[req->id].request)); + info->shadow[req->id].req = *req; + info->ring.req_prod_pvt++; + } -static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - switch ( msg->subtype ) - { - case CMSG_BLKIF_FE_INTERFACE_STATUS: - blkif_status((blkif_fe_interface_status_t *) - &msg->msg[0]); - break; - default: - msg->length = 0; - break; - } - - ctrl_if_send_response(msg); -} + kfree(copy); -int wait_for_blkif(void) -{ - int err = 0; - int i; - send_driver_status(1); - - /* - * We should read 'nr_interfaces' from response message and wait - * for notifications before proceeding. For now we assume that we - * will be notified of exactly one interface. - */ - for ( i=0; (blkif_state != BLKIF_STATE_CONNECTED) && (i < 10*HZ); i++ ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if ( blkif_state != BLKIF_STATE_CONNECTED ) - { - printk(KERN_INFO "xen_blk: Timeout connecting to device!\n"); - err = -ENOSYS; - } - return err; -} + (void)xenbus_switch_state(info->xbdev, XenbusStateConnected); -int __init xlblk_init(void) -{ - int i; + spin_lock_irq(&blkif_io_lock); + + /* Now safe for us to use the shared ring */ + info->connected = BLKIF_STATE_CONNECTED; -#ifdef CONFIG_XEN_BLKDEV_GRANT - if ( 0 > gnttab_alloc_grant_references( MAXIMUM_OUTSTANDING_BLOCK_REQS, - &gref_head, &gref_terminal )) - return 1; - printk(KERN_ALERT "Blkif frontend is using grant tables.\n"); -#endif + /* Send off requeued requests */ + flush_requests(info); - if ( (xen_start_info.flags & SIF_INITDOMAIN) || - (xen_start_info.flags & SIF_BLK_BE_DOMAIN) ) - return 0; + /* Kick any other new requests queued since we resumed */ + kick_pending_request_queues(info); - printk(KERN_INFO "xen_blk: Initialising virtual block device driver\n"); + spin_unlock_irq(&blkif_io_lock); +} - blk_shadow_free = 0; - memset(blk_shadow, 0, sizeof(blk_shadow)); - for ( i = 0; i < BLK_RING_SIZE; i++ ) - blk_shadow[i].req.id = i+1; - blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; - (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); +/* ** Driver Registration ** */ - wait_for_blkif(); - return 0; -} +static struct xenbus_device_id blkfront_ids[] = { + { "vbd" }, + { "" } +}; -void blkdev_suspend(void) -{ -} -void blkdev_resume(void) +static struct xenbus_driver blkfront = { + .name = "vbd", + .owner = THIS_MODULE, + .ids = blkfront_ids, + .probe = blkfront_probe, + .remove = blkfront_remove, + .resume = blkfront_resume, + .otherend_changed = backend_changed, +}; + + +static int __init xlblk_init(void) { -#ifdef CONFIG_XEN_BLKDEV_GRANT - int i, j; - for ( i = 0; i < BLK_RING_SIZE; i++ ) - for ( j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++ ) - blk_shadow[i].req.frame_and_sects[j] |= GRANTREF_INVALID; -#endif - send_driver_status(1); + if (!is_running_on_xen()) + return -ENODEV; + + return xenbus_register_frontend(&blkfront); } +module_init(xlblk_init); -static void blkif_completion(struct blk_shadow *s) + +static void xlblk_exit(void) { - int i; -#ifdef CONFIG_XEN_BLKDEV_GRANT - for ( i = 0; i < s->req.nr_segments; i++ ) - gnttab_release_grant_reference( - &gref_head, blkif_gref_from_fas(s->req.frame_and_sects[i])); -#else - /* This is a hack to get the dirty logging bits set */ - if ( s->req.operation == BLKIF_OP_READ ) - { - for ( i = 0; i < s->req.nr_segments; i++ ) - { - unsigned long pfn = s->req.frame_and_sects[i] >> PAGE_SHIFT; - unsigned long mfn = phys_to_machine_mapping[pfn]; - xen_machphys_update(mfn, pfn); - } - } -#endif + return xenbus_unregister_driver(&blkfront); } +module_exit(xlblk_exit); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/blkfront/block.h b/drivers/xen/blkfront/block.h index ede57abfa..5ba3d1ebc 100644 --- a/drivers/xen/blkfront/block.h +++ b/drivers/xen/blkfront/block.h @@ -7,8 +7,11 @@ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge * Copyright (c) 2004-2005, Christian Limpach * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without @@ -33,6 +36,7 @@ #define __XEN_DRIVERS_BLOCK_H__ #include +#include #include #include #include @@ -44,74 +48,109 @@ #include #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include -#if 0 -#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a ) +#if 1 +#define IPRINTK(fmt, args...) \ + printk(KERN_INFO "xen_blk: " fmt, ##args) +#else +#define IPRINTK(fmt, args...) ((void)0) +#endif + +#if 1 +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_blk: " fmt, ##args) #else -#define DPRINTK(_f, _a...) ((void)0) +#define WPRINTK(fmt, args...) ((void)0) #endif +#define DPRINTK(_f, _a...) pr_debug(_f, ## _a) + #if 0 -#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a ) +#define DPRINTK_IOCTL(_f, _a...) printk(KERN_ALERT _f, ## _a) #else #define DPRINTK_IOCTL(_f, _a...) ((void)0) #endif -struct xlbd_type_info { - int partn_shift; - int partn_per_major; - int devs_per_major; - char *devname; - char *diskname; +struct xlbd_type_info +{ + int partn_shift; + int disks_per_major; + char *devname; + char *diskname; +}; + +struct xlbd_major_info +{ + int major; + int index; + int usage; + struct xlbd_type_info *type; }; +struct blk_shadow { + blkif_request_t req; + unsigned long request; + unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; + +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) + /* * We have one of these per vbd, whether ide, scsi or 'other'. They * hang in private_data off the gendisk structure. We may end up * putting all kinds of interesting stuff here :-) */ -struct xlbd_major_info { - int major; - int index; - int usage; - struct xlbd_type_info *type; -}; +struct blkfront_info +{ + struct xenbus_device *xbdev; + dev_t dev; + struct gendisk *gd; + int vdevice; + blkif_vdev_t handle; + int connected; + int ring_ref; + blkif_front_ring_t ring; + unsigned int evtchn, irq; + struct xlbd_major_info *mi; + request_queue_t *rq; + struct work_struct work; + struct gnttab_free_callback callback; + struct blk_shadow shadow[BLK_RING_SIZE]; + unsigned long shadow_free; -struct xlbd_disk_info { - int xd_device; - struct xlbd_major_info *mi; + /** + * The number of people holding this device open. We won't allow a + * hot-unplug unless this is 0. + */ + int users; }; -typedef struct xen_block { - int usage; -} xen_block_t; - -extern struct request_queue *xlbd_blk_queue; extern spinlock_t blkif_io_lock; extern int blkif_open(struct inode *inode, struct file *filep); extern int blkif_release(struct inode *inode, struct file *filep); extern int blkif_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument); + unsigned command, unsigned long argument); +extern int blkif_getgeo(struct block_device *, struct hd_geometry *); extern int blkif_check(dev_t dev); extern int blkif_revalidate(dev_t dev); -extern void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp); -#ifdef CONFIG_XEN_BLKDEV_GRANT -extern void blkif_control_probe_send( - blkif_request_t *req, blkif_response_t *rsp, unsigned long address); -#endif -extern void do_blkif_request (request_queue_t *rq); - -extern void xlvbd_update_vbds(void); +extern void do_blkif_request (request_queue_t *rq); /* Virtual block-device subsystem. */ -extern int xlvbd_init(void); -extern void xlvbd_cleanup(void); +/* Note that xlvbd_add doesn't call add_disk for you: you're expected + to call add_disk on info->gd once the disk is properly connected + up. */ +int xlvbd_add(blkif_sector_t capacity, int device, + u16 vdisk_info, u16 sector_size, struct blkfront_info *info); +void xlvbd_del(struct blkfront_info *info); #endif /* __XEN_DRIVERS_BLOCK_H__ */ diff --git a/drivers/xen/blkfront/vbd.c b/drivers/xen/blkfront/vbd.c index b5f2b14b4..8aa453d3a 100644 --- a/drivers/xen/blkfront/vbd.c +++ b/drivers/xen/blkfront/vbd.c @@ -7,8 +7,11 @@ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge * Copyright (c) 2004-2005, Christian Limpach * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without @@ -33,6 +36,9 @@ #include #include +#define BLKIF_MAJOR(dev) ((dev)>>8) +#define BLKIF_MINOR(dev) ((dev) & 0xff) + /* * For convenience we distinguish between ide, scsi and 'other' (i.e., * potentially combinations of the two) in the naming scheme and in a few other @@ -43,465 +49,270 @@ #define NUM_SCSI_MAJORS 9 #define NUM_VBD_MAJORS 1 -struct lvdisk -{ - blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */ - blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */ - u16 info; - struct list_head list; -}; - static struct xlbd_type_info xlbd_ide_type = { - .partn_shift = 6, - .partn_per_major = 2, - .devname = "ide", - .diskname = "hd", + .partn_shift = 6, + .disks_per_major = 2, + .devname = "ide", + .diskname = "hd", }; static struct xlbd_type_info xlbd_scsi_type = { - .partn_shift = 4, - .partn_per_major = 16, - .devname = "sd", - .diskname = "sd", + .partn_shift = 4, + .disks_per_major = 16, + .devname = "sd", + .diskname = "sd", }; static struct xlbd_type_info xlbd_vbd_type = { - .partn_shift = 4, - .partn_per_major = 16, - .devname = "xvd", - .diskname = "xvd", + .partn_shift = 4, + .disks_per_major = 16, + .devname = "xvd", + .diskname = "xvd", }; static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS + - NUM_VBD_MAJORS]; + NUM_VBD_MAJORS]; -#define XLBD_MAJOR_IDE_START 0 -#define XLBD_MAJOR_SCSI_START (NUM_IDE_MAJORS) -#define XLBD_MAJOR_VBD_START (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) +#define XLBD_MAJOR_IDE_START 0 +#define XLBD_MAJOR_SCSI_START (NUM_IDE_MAJORS) +#define XLBD_MAJOR_VBD_START (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) -#define XLBD_MAJOR_IDE_RANGE XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1 -#define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1 -#define XLBD_MAJOR_VBD_RANGE XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1 +#define XLBD_MAJOR_IDE_RANGE XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1 +#define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1 +#define XLBD_MAJOR_VBD_RANGE XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1 /* Information about our VBDs. */ #define MAX_VBDS 64 -struct list_head vbds_list; +static LIST_HEAD(vbds_list); -struct request_queue *xlbd_blk_queue = NULL; - -#define MAJOR_XEN(dev) ((dev)>>8) -#define MINOR_XEN(dev) ((dev) & 0xff) - -static struct block_device_operations xlvbd_block_fops = +static struct block_device_operations xlvbd_block_fops = { - .owner = THIS_MODULE, - .open = blkif_open, - .release = blkif_release, - .ioctl = blkif_ioctl, + .owner = THIS_MODULE, + .open = blkif_open, + .release = blkif_release, + .ioctl = blkif_ioctl, + .getgeo = blkif_getgeo }; -spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(blkif_io_lock); -static struct lvdisk * xlvbd_device_alloc(void) +static struct xlbd_major_info * +xlbd_alloc_major_info(int major, int minor, int index) { - struct lvdisk *ret; - - ret = kmalloc(sizeof(struct lvdisk), GFP_KERNEL); - if ( ret ) { - memset(ret, '\0', sizeof(struct lvdisk)); - INIT_LIST_HEAD(&ret->list); - } - return ret; + struct xlbd_major_info *ptr; + + ptr = kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); + if (ptr == NULL) + return NULL; + + ptr->major = major; + + switch (index) { + case XLBD_MAJOR_IDE_RANGE: + ptr->type = &xlbd_ide_type; + ptr->index = index - XLBD_MAJOR_IDE_START; + break; + case XLBD_MAJOR_SCSI_RANGE: + ptr->type = &xlbd_scsi_type; + ptr->index = index - XLBD_MAJOR_SCSI_START; + break; + case XLBD_MAJOR_VBD_RANGE: + ptr->type = &xlbd_vbd_type; + ptr->index = index - XLBD_MAJOR_VBD_START; + break; + } + + printk("Registering block device major %i\n", ptr->major); + if (register_blkdev(ptr->major, ptr->type->devname)) { + WPRINTK("can't get major %d with name %s\n", + ptr->major, ptr->type->devname); + kfree(ptr); + return NULL; + } + + devfs_mk_dir(ptr->type->devname); + major_info[index] = ptr; + return ptr; } -static void xlvbd_device_free(struct lvdisk *disk) +static struct xlbd_major_info * +xlbd_get_major_info(int vdevice) { - list_del(&disk->list); - kfree(disk); + struct xlbd_major_info *mi; + int major, minor, index; + + major = BLKIF_MAJOR(vdevice); + minor = BLKIF_MINOR(vdevice); + + switch (major) { + case IDE0_MAJOR: index = 0; break; + case IDE1_MAJOR: index = 1; break; + case IDE2_MAJOR: index = 2; break; + case IDE3_MAJOR: index = 3; break; + case IDE4_MAJOR: index = 4; break; + case IDE5_MAJOR: index = 5; break; + case IDE6_MAJOR: index = 6; break; + case IDE7_MAJOR: index = 7; break; + case IDE8_MAJOR: index = 8; break; + case IDE9_MAJOR: index = 9; break; + case SCSI_DISK0_MAJOR: index = 10; break; + case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: + index = 11 + major - SCSI_DISK1_MAJOR; + break; + case SCSI_CDROM_MAJOR: index = 18; break; + default: index = 19; break; + } + + mi = ((major_info[index] != NULL) ? major_info[index] : + xlbd_alloc_major_info(major, minor, index)); + if (mi) + mi->usage++; + return mi; } -static vdisk_t * xlvbd_probe(int *ret) +static void +xlbd_put_major_info(struct xlbd_major_info *mi) { - blkif_response_t rsp; - blkif_request_t req; - vdisk_t *disk_info = NULL; - unsigned long buf; - int nr; - - buf = __get_free_page(GFP_KERNEL); - if ( !buf ) - goto out; - - memset(&req, 0, sizeof(req)); - req.operation = BLKIF_OP_PROBE; - req.nr_segments = 1; -#ifdef CONFIG_XEN_BLKDEV_GRANT - blkif_control_probe_send(&req, &rsp, - (unsigned long)(virt_to_machine(buf))); -#else - req.frame_and_sects[0] = virt_to_machine(buf) | 7; - - blkif_control_send(&req, &rsp); -#endif - if ( rsp.status <= 0 ) { - printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status); - goto out; - } - nr = rsp.status; - if ( nr > MAX_VBDS ) - nr = MAX_VBDS; - - disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL); - if ( disk_info ) - memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t)); - if ( ret ) - *ret = nr; -out: - free_page(buf); - return disk_info; + mi->usage--; + /* XXX: release major if 0 */ } -static struct xlbd_major_info *xlbd_alloc_major_info(int major, int minor, int index) +static int +xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) { - struct xlbd_major_info *ptr; - - ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); - if ( !ptr ) - return NULL; - - memset(ptr, 0, sizeof(struct xlbd_major_info)); - - ptr->major = major; - - switch (index) { - case XLBD_MAJOR_IDE_RANGE: - ptr->type = &xlbd_ide_type; - ptr->index = index - XLBD_MAJOR_IDE_START; - break; - case XLBD_MAJOR_SCSI_RANGE: - ptr->type = &xlbd_scsi_type; - ptr->index = index - XLBD_MAJOR_SCSI_START; - break; - case XLBD_MAJOR_VBD_RANGE: - ptr->type = &xlbd_vbd_type; - ptr->index = index - XLBD_MAJOR_VBD_START; - break; - } - - if ( register_blkdev(ptr->major, ptr->type->devname) ) { - printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n", - ptr->major, ptr->type->devname); - kfree(ptr); - return NULL; - } - - devfs_mk_dir(ptr->type->devname); - major_info[index] = ptr; - return ptr; -} + request_queue_t *rq; -static struct xlbd_major_info *xlbd_get_major_info(int device) -{ - int major, minor, index; - - major = MAJOR_XEN(device); - minor = MINOR_XEN(device); - - switch (major) { - case IDE0_MAJOR: index = 0; break; - case IDE1_MAJOR: index = 1; break; - case IDE2_MAJOR: index = 2; break; - case IDE3_MAJOR: index = 3; break; - case IDE4_MAJOR: index = 4; break; - case IDE5_MAJOR: index = 5; break; - case IDE6_MAJOR: index = 6; break; - case IDE7_MAJOR: index = 7; break; - case IDE8_MAJOR: index = 8; break; - case IDE9_MAJOR: index = 9; break; - case SCSI_DISK0_MAJOR: index = 10; break; - case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: - index = 11 + major - SCSI_DISK1_MAJOR; - break; - case SCSI_CDROM_MAJOR: index = 18; break; - default: index = 19; break; - } - - return major_info[index] - ? major_info[index] - : xlbd_alloc_major_info(major, minor, index); -} + rq = blk_init_queue(do_blkif_request, &blkif_io_lock); + if (rq == NULL) + return -1; -static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type) -{ - xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock); - if ( !xlbd_blk_queue ) - return -1; - - elevator_init(xlbd_blk_queue, "noop"); - - /* - * Turn off barking 'headactive' mode. We dequeue - * buffer heads as soon as we pass them to back-end - * driver. - */ - blk_queue_headactive(xlbd_blk_queue, 0); - - /* Hard sector size and max sectors impersonate the equiv. hardware. */ - blk_queue_hardsect_size(xlbd_blk_queue, 512); - blk_queue_max_sectors(xlbd_blk_queue, 512); - - /* Each segment in a request is up to an aligned page in size. */ - blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1); - blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE); - - /* Ensure a merged request will fit in a single I/O ring slot. */ - blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); - blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); - - /* Make sure buffer addresses are sector-aligned. */ - blk_queue_dma_alignment(xlbd_blk_queue, 511); - return 0; -} + elevator_init(rq, "noop"); -struct gendisk *xlvbd_alloc_gendisk(struct xlbd_major_info *mi, int minor, - vdisk_t *disk) -{ - struct gendisk *gd; - struct xlbd_disk_info *di; - int nb_minors; - - di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL); - if ( !di ) - goto out; - di->mi = mi; - di->xd_device = disk->device; - - nb_minors = ((minor & ((1 << mi->type->partn_shift) - 1)) == 0) - ? mi->type->partn_per_major - : 1; - - gd = alloc_disk(nb_minors); - if ( !gd ) - goto out; - - if ( nb_minors > 1 ) - sprintf(gd->disk_name, "%s%c", mi->type->diskname, - 'a' + mi->index * mi->type->partn_per_major + - (minor >> mi->type->partn_shift)); - else - sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, - 'a' + mi->index * mi->type->partn_per_major + - (minor >> mi->type->partn_shift), - minor & ((1 << mi->type->partn_shift) - 1)); - - gd->major = mi->major; - gd->first_minor = minor; - gd->fops = &xlvbd_block_fops; - gd->private_data = di; - set_capacity(gd, disk->capacity); - - if ( !xlbd_blk_queue ) - if ( xlvbd_blk_queue_alloc(mi->type) ) - goto out_gendisk; - - gd->queue = xlbd_blk_queue; - add_disk(gd); - return gd; -out_gendisk: - printk(KERN_ALERT "error gendisk\n"); - del_gendisk(gd); -out: - printk(KERN_ALERT "error out\n"); - kfree(di); - return NULL; -} + /* Hard sector size and max sectors impersonate the equiv. hardware. */ + blk_queue_hardsect_size(rq, sector_size); + blk_queue_max_sectors(rq, 512); -static int xlvbd_device_add(struct list_head *list, vdisk_t *disk) -{ - struct lvdisk *new; - int minor; - dev_t device; - struct block_device *bd; - struct gendisk *gd; - struct xlbd_major_info *mi; - - mi = xlbd_get_major_info(disk->device); - if ( !mi ) - return -EPERM; - - new = xlvbd_device_alloc(); - if ( !new ) - return -1; - new->capacity = disk->capacity; - new->device = disk->device; - new->info = disk->info; - - minor = MINOR_XEN(disk->device); - device = MKDEV(mi->major, minor); - - bd = bdget(device); - if ( !bd ) - goto out; - - gd = xlvbd_alloc_gendisk(mi, minor, disk); - if ( !gd ) - goto out_bd; - - if ( VDISK_READONLY(disk->info) ) - set_disk_ro(gd, 1); - - switch (VDISK_TYPE(disk->info)) { - case VDISK_TYPE_CDROM: - gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; - break; - case VDISK_TYPE_FLOPPY: - case VDISK_TYPE_TAPE: - gd->flags |= GENHD_FL_REMOVABLE; - break; - case VDISK_TYPE_DISK: - break; - default: - printk(KERN_ALERT "XenLinux: unknown device type %d\n", - VDISK_TYPE(disk->info)); - break; - } - - list_add(&new->list, list); -out_bd: - bdput(bd); -out: - return 0; -} + /* Each segment in a request is up to an aligned page in size. */ + blk_queue_segment_boundary(rq, PAGE_SIZE - 1); + blk_queue_max_segment_size(rq, PAGE_SIZE); -static int xlvbd_device_del(struct lvdisk *disk) -{ - dev_t device; - struct block_device *bd; - struct gendisk *gd; - struct xlbd_disk_info *di; - int ret = 0, unused; + /* Ensure a merged request will fit in a single I/O ring slot. */ + blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST); + blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST); - device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device)); + /* Make sure buffer addresses are sector-aligned. */ + blk_queue_dma_alignment(rq, 511); - bd = bdget(device); - if ( !bd ) - return -1; + gd->queue = rq; - gd = get_gendisk(device, &unused); - di = gd->private_data; - - if ( di->mi->usage != 0 ) { - printk(KERN_ALERT "VBD removal failed: used [dev=%x]\n", device); - ret = -1; - goto out; - } - - del_gendisk(gd); - - xlvbd_device_free(disk); -out: - bdput(bd); - return ret; + return 0; } -static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk) +static int +xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, int vdevice, + u16 vdisk_info, u16 sector_size, + struct blkfront_info *info) { - dev_t device; - struct block_device *bd; - struct gendisk *gd; - int unused; - - if ( ldisk->capacity == disk->capacity && ldisk->info == disk->info ) - return 0; + struct gendisk *gd; + struct xlbd_major_info *mi; + int nr_minors = 1; + int err = -ENODEV; + + BUG_ON(info->gd != NULL); + BUG_ON(info->mi != NULL); + BUG_ON(info->rq != NULL); + + mi = xlbd_get_major_info(vdevice); + if (mi == NULL) + goto out; + info->mi = mi; + + if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0) + nr_minors = 1 << mi->type->partn_shift; + + gd = alloc_disk(nr_minors); + if (gd == NULL) + goto out; + + if (nr_minors > 1) + sprintf(gd->disk_name, "%s%c", mi->type->diskname, + 'a' + mi->index * mi->type->disks_per_major + + (minor >> mi->type->partn_shift)); + else + sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, + 'a' + mi->index * mi->type->disks_per_major + + (minor >> mi->type->partn_shift), + minor & ((1 << mi->type->partn_shift) - 1)); + + gd->major = mi->major; + gd->first_minor = minor; + gd->fops = &xlvbd_block_fops; + gd->private_data = info; + gd->driverfs_dev = &(info->xbdev->dev); + set_capacity(gd, capacity); + + if (xlvbd_init_blk_queue(gd, sector_size)) { + del_gendisk(gd); + goto out; + } + + info->rq = gd->queue; + + if (vdisk_info & VDISK_READONLY) + set_disk_ro(gd, 1); + + if (vdisk_info & VDISK_REMOVABLE) + gd->flags |= GENHD_FL_REMOVABLE; + + if (vdisk_info & VDISK_CDROM) + gd->flags |= GENHD_FL_CD; + + info->gd = gd; + + return 0; + + out: + if (mi) + xlbd_put_major_info(mi); + info->mi = NULL; + return err; +} - device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device)); +int +xlvbd_add(blkif_sector_t capacity, int vdevice, u16 vdisk_info, + u16 sector_size, struct blkfront_info *info) +{ + struct block_device *bd; + int err = 0; - bd = bdget(device); - if ( !bd ) - return -1; + info->dev = MKDEV(BLKIF_MAJOR(vdevice), BLKIF_MINOR(vdevice)); - gd = get_gendisk(device, &unused); - set_capacity(gd, disk->capacity); - ldisk->capacity = disk->capacity; + bd = bdget(info->dev); + if (bd == NULL) + return -ENODEV; - bdput(bd); + err = xlvbd_alloc_gendisk(BLKIF_MINOR(vdevice), capacity, vdevice, + vdisk_info, sector_size, info); - return 0; + bdput(bd); + return err; } -void xlvbd_refresh(void) +void +xlvbd_del(struct blkfront_info *info) { - vdisk_t *newdisks; - struct list_head *tmp, *tmp2; - struct lvdisk *disk; - int i, nr; - - newdisks = xlvbd_probe(&nr); - if ( !newdisks ) { - printk(KERN_ALERT "failed to probe\n"); - return; - } - - i = 0; - list_for_each_safe(tmp, tmp2, &vbds_list) { - disk = list_entry(tmp, struct lvdisk, list); - - for (i = 0; i < nr; i++) { - if ( !newdisks[i].device ) - continue; - if ( disk->device == newdisks[i].device ) { - xlvbd_device_update(disk, &newdisks[i]); - newdisks[i].device = 0; - break; - } - } - if ( i == nr ) { - xlvbd_device_del(disk); - newdisks[i].device = 0; - } - } - for (i = 0; i < nr; i++) - if ( newdisks[i].device ) - xlvbd_device_add(&vbds_list, &newdisks[i]); - kfree(newdisks); -} + if (info->mi == NULL) + return; -/* - * xlvbd_update_vbds - reprobes the VBD status and performs updates driver - * state. The VBDs need to be updated in this way when the domain is - * initialised and also each time we receive an XLBLK_UPDATE event. - */ -void xlvbd_update_vbds(void) -{ - xlvbd_refresh(); -} + BUG_ON(info->gd == NULL); + del_gendisk(info->gd); + put_disk(info->gd); + info->gd = NULL; -/* - * Set up all the linux device goop for the virtual block devices - * (vbd's) that we know about. Note that although from the backend - * driver's p.o.v. VBDs are addressed simply an opaque 16-bit device - * number, the domain creation tools conventionally allocate these - * numbers to correspond to those used by 'real' linux -- this is just - * for convenience as it means e.g. that the same /etc/fstab can be - * used when booting with or without Xen. - */ -int xlvbd_init(void) -{ - int i, nr; - vdisk_t *disks; - - INIT_LIST_HEAD(&vbds_list); - - memset(major_info, 0, sizeof(major_info)); - - disks = xlvbd_probe(&nr); - if ( !disks ) { - printk(KERN_ALERT "failed to probe\n"); - return -1; - } - - for (i = 0; i < nr; i++) - xlvbd_device_add(&vbds_list, &disks[i]); - kfree(disks); - return 0; + xlbd_put_major_info(info->mi); + info->mi = NULL; + + BUG_ON(info->rq == NULL); + blk_cleanup_queue(info->rq); + info->rq = NULL; } diff --git a/drivers/xen/blktap/Makefile b/drivers/xen/blktap/Makefile index 80b7ca062..409b07896 100644 --- a/drivers/xen/blktap/Makefile +++ b/drivers/xen/blktap/Makefile @@ -1,3 +1,3 @@ - -obj-y := blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o +LINUXINCLUDE += -I../xen/include/public/io +obj-y := xenbus.o interface.o blktap.o diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c index a9a00677b..8c5cf68d7 100644 --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -1,87 +1,1450 @@ /****************************************************************************** - * blktap.c + * drivers/xen/blktap/blktap.c * - * XenLinux virtual block-device tap. + * Back-end driver for user level virtual block devices. This portion of the + * driver exports a 'unified' block-device interface that can be accessed + * by any operating system that implements a compatible front end. Requests + * are remapped to a user-space memory region. + * + * Based on the blkback driver code. * - * Copyright (c) 2004, Andrew Warfield + * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield * - * Based on the original split block driver: - * Copyright (c) 2003-2004, Keir Fraser & Steve Hand - * Modifications by Mark A. Williamson are (c) Intel Research Cambridge - * Copyright (c) 2004, Christian Limpach + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * Note that unlike the split block driver code, this driver has been developed - * strictly for Linux 2.6 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TAP_DEV 100 /*the maximum number of tapdisk ring devices */ +#define MAX_DEV_NAME 100 /*the max tapdisk ring device name e.g. blktap0 */ + +/* + * The maximum number of requests that can be outstanding at any time + * is determined by + * + * [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] + * + * where mmap_alloc < MAX_DYNAMIC_MEM. + * + * TODO: + * mmap_alloc is initialised to 2 and should be adjustable on the fly via + * sysfs. */ +#define MAX_DYNAMIC_MEM 64 +#define MAX_PENDING_REQS 64 +#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST) +#define MMAP_VADDR(_start, _req,_seg) \ + (_start + \ + ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \ + ((_seg) * PAGE_SIZE)) +static int blkif_reqs = MAX_PENDING_REQS; +static int mmap_pages = MMAP_PAGES; + +#define RING_PAGES 1 /* BLKTAP - immediately before the mmap area, we + * have a bunch of pages reserved for shared + * memory rings. + */ + +/*Data struct associated with each of the tapdisk devices*/ +typedef struct tap_blkif { + struct vm_area_struct *vma; /*Shared memory area */ + unsigned long rings_vstart; /*Kernel memory mapping */ + unsigned long user_vstart; /*User memory mapping */ + unsigned long dev_inuse; /*One process opens device at a time. */ + unsigned long dev_pending; /*In process of being opened */ + unsigned long ring_ok; /*make this ring->state */ + blkif_front_ring_t ufe_ring; /*Rings up to user space. */ + wait_queue_head_t wait; /*for poll */ + unsigned long mode; /*current switching mode */ + int minor; /*Minor number for tapdisk device */ + pid_t pid; /*tapdisk process id */ + enum { RUNNING, CLEANSHUTDOWN } status; /*Detect a clean userspace + shutdown */ + unsigned long *idx_map; /*Record the user ring id to kern + [req id, idx] tuple */ + blkif_t *blkif; /*Associate blkif with tapdev */ +} tap_blkif_t; + +/*Private data struct associated with the inode*/ +typedef struct private_info { + int idx; +} private_info_t; + +/*Data struct handed back to userspace for tapdisk device to VBD mapping*/ +typedef struct domid_translate { + unsigned short domid; + unsigned short busid; +} domid_translate_t ; -#include "blktap.h" -int __init xlblktap_init(void) +domid_translate_t translate_domid[MAX_TAP_DEV]; +tap_blkif_t *tapfds[MAX_TAP_DEV]; + +static int __init set_blkif_reqs(char *str) { - ctrl_msg_t cmsg; - blkif_fe_driver_status_t fe_st; - blkif_be_driver_status_t be_st; + get_option(&str, &blkif_reqs); + return 1; +} +__setup("blkif_reqs=", set_blkif_reqs); + +/* Run-time switchable: /sys/module/blktap/parameters/ */ +static unsigned int log_stats = 0; +static unsigned int debug_lvl = 0; +module_param(log_stats, int, 0644); +module_param(debug_lvl, int, 0644); + +/* + * Each outstanding request that we've passed to the lower device layers has a + * 'pending_req' allocated to it. Each buffer_head that completes decrements + * the pendcnt towards zero. When it hits zero, the specified domain has a + * response queued for it, with the saved 'id' passed back. + */ +typedef struct { + blkif_t *blkif; + unsigned long id; + unsigned short mem_idx; + int nr_pages; + atomic_t pendcnt; + unsigned short operation; + int status; + struct list_head free_list; + int inuse; +} pending_req_t; + +static pending_req_t *pending_reqs[MAX_PENDING_REQS]; +static struct list_head pending_free; +static DEFINE_SPINLOCK(pending_free_lock); +static DECLARE_WAIT_QUEUE_HEAD (pending_free_wq); +static int alloc_pending_reqs; + +typedef unsigned int PEND_RING_IDX; + +static inline int MASK_PEND_IDX(int i) { + return (i & (MAX_PENDING_REQS-1)); +} + +static inline unsigned int RTN_PEND_IDX(pending_req_t *req, int idx) { + return (req - pending_reqs[idx]); +} + +#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons) + +#define BLKBACK_INVALID_HANDLE (~0) + +typedef struct mmap_page { + unsigned long start; + struct page *mpage; +} mmap_page_t; + +static mmap_page_t mmap_start[MAX_DYNAMIC_MEM]; +static unsigned short mmap_alloc = 0; +static unsigned short mmap_lock = 0; +static unsigned short mmap_inuse = 0; +static unsigned long *pending_addrs[MAX_DYNAMIC_MEM]; + +/****************************************************************** + * GRANT HANDLES + */ + +/* When using grant tables to map a frame for device access then the + * handle returned must be used to unmap the frame. This is needed to + * drop the ref count on the frame. + */ +struct grant_handle_pair +{ + grant_handle_t kernel; + grant_handle_t user; +}; + +static struct grant_handle_pair + pending_grant_handles[MAX_DYNAMIC_MEM][MMAP_PAGES]; +#define pending_handle(_id, _idx, _i) \ + (pending_grant_handles[_id][((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) \ + + (_i)]) - printk(KERN_INFO "Initialising Xen block tap device\n"); - DPRINTK(" tap - Backend connection init:\n"); +static int blktap_read_ufe_ring(int idx); /*local prototypes*/ +#define BLKTAP_MINOR 0 /*/dev/xen/blktap resides at device number + major=254, minor numbers begin at 0 */ +#define BLKTAP_DEV_MAJOR 254 /* TODO: Make major number dynamic * + * and create devices in the kernel * + */ +#define BLKTAP_DEV_DIR "/dev/xen" - (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); +/* blktap IOCTLs: */ +#define BLKTAP_IOCTL_KICK_FE 1 +#define BLKTAP_IOCTL_KICK_BE 2 /* currently unused */ +#define BLKTAP_IOCTL_SETMODE 3 +#define BLKTAP_IOCTL_SENDPID 4 +#define BLKTAP_IOCTL_NEWINTF 5 +#define BLKTAP_IOCTL_MINOR 6 +#define BLKTAP_IOCTL_MAJOR 7 +#define BLKTAP_QUERY_ALLOC_REQS 8 +#define BLKTAP_IOCTL_FREEINTF 9 +#define BLKTAP_IOCTL_PRINT_IDXS 100 - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_BLKIF_FE; - cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS; - cmsg.length = sizeof(blkif_fe_driver_status_t); - fe_st.status = BLKIF_DRIVER_STATUS_UP; - memcpy(cmsg.msg, &fe_st, sizeof(fe_st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); +/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */ +#define BLKTAP_MODE_PASSTHROUGH 0x00000000 /* default */ +#define BLKTAP_MODE_INTERCEPT_FE 0x00000001 +#define BLKTAP_MODE_INTERCEPT_BE 0x00000002 /* unimp. */ + +#define BLKTAP_MODE_INTERPOSE \ + (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE) + + +static inline int BLKTAP_MODE_VALID(unsigned long arg) +{ + return ((arg == BLKTAP_MODE_PASSTHROUGH ) || + (arg == BLKTAP_MODE_INTERCEPT_FE) || + (arg == BLKTAP_MODE_INTERPOSE )); +} + +/* Requests passing through the tap to userspace are re-assigned an ID. + * We must record a mapping between the BE [IDX,ID] tuple and the userspace + * ring ID. + */ + +static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx) +{ + return ((fe_dom << 16) | MASK_PEND_IDX(idx)); +} + +extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id) +{ + return (PEND_RING_IDX)(id & 0x0000ffff); +} + +extern inline int ID_TO_MIDX(unsigned long id) +{ + return (int)(id >> 16); +} + +#define INVALID_REQ 0xdead0000 + +/*TODO: Convert to a free list*/ +static inline int GET_NEXT_REQ(unsigned long *idx_map) +{ + int i; + for (i = 0; i < MAX_PENDING_REQS; i++) + if (idx_map[i] == INVALID_REQ) return i; + + return INVALID_REQ; +} + + +#define BLKTAP_INVALID_HANDLE(_g) \ + (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF)) + +#define BLKTAP_INVALIDATE_HANDLE(_g) do { \ + (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \ + } while(0) + + +/****************************************************************** + * BLKTAP VM OPS + */ + +static struct page *blktap_nopage(struct vm_area_struct *vma, + unsigned long address, + int *type) +{ + /* + * if the page has not been mapped in by the driver then return + * NOPAGE_SIGBUS to the domain. + */ + + return NOPAGE_SIGBUS; +} + +struct vm_operations_struct blktap_vm_ops = { + nopage: blktap_nopage, +}; + +/****************************************************************** + * BLKTAP FILE OPS + */ + +/*Function Declarations*/ +static int get_next_free_dev(void); +static int blktap_open(struct inode *inode, struct file *filp); +static int blktap_release(struct inode *inode, struct file *filp); +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma); +static int blktap_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static unsigned int blktap_poll(struct file *file, poll_table *wait); - DPRINTK(" tap - Frontend connection init:\n"); +struct miscdevice *set_misc(int minor, char *name, int dev); + +static struct file_operations blktap_fops = { + .owner = THIS_MODULE, + .poll = blktap_poll, + .ioctl = blktap_ioctl, + .open = blktap_open, + .release = blktap_release, + .mmap = blktap_mmap, +}; + + +static int get_next_free_dev(void) +{ + tap_blkif_t *info; + int i = 0, ret = -1; + unsigned long flags; + + spin_lock_irqsave(&pending_free_lock, flags); + + while (i < MAX_TAP_DEV) { + info = tapfds[i]; + if ( (tapfds[i] != NULL) && (info->dev_inuse == 0) + && (info->dev_pending == 0) ) { + info->dev_pending = 1; + ret = i; + goto done; + } + i++; + } + +done: + spin_unlock_irqrestore(&pending_free_lock, flags); + return ret; +} + +int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif) +{ + int i; + + for (i = 0; i < MAX_TAP_DEV; i++) + if ( (translate_domid[i].domid == domid) + && (translate_domid[i].busid == xenbus_id) ) { + tapfds[i]->blkif = blkif; + tapfds[i]->status = RUNNING; + return i; + } + return -1; +} + +void signal_tapdisk(int idx) +{ + tap_blkif_t *info; + struct task_struct *ptask; + + info = tapfds[idx]; + if ( (idx > 0) && (idx < MAX_TAP_DEV) && (info->pid > 0) ) { + ptask = find_task_by_pid(info->pid); + if (ptask) { + info->status = CLEANSHUTDOWN; + } + } + info->blkif = NULL; + return; +} + +static int blktap_open(struct inode *inode, struct file *filp) +{ + blkif_sring_t *sring; + int idx = iminor(inode) - BLKTAP_MINOR; + tap_blkif_t *info; + private_info_t *prv; + int i; + + if (tapfds[idx] == NULL) { + WPRINTK("Unable to open device /dev/xen/blktap%d\n", + idx); + return -ENOMEM; + } + DPRINTK("Opening device /dev/xen/blktap%d\n",idx); + + info = tapfds[idx]; + + /*Only one process can access device at a time*/ + if (test_and_set_bit(0, &info->dev_inuse)) + return -EBUSY; + + info->dev_pending = 0; + + /* Allocate the fe ring. */ + sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL); + if (sring == NULL) + goto fail_nomem; + + SetPageReserved(virt_to_page(sring)); + + SHARED_RING_INIT(sring); + FRONT_RING_INIT(&info->ufe_ring, sring, PAGE_SIZE); + + prv = kzalloc(sizeof(private_info_t),GFP_KERNEL); + prv->idx = idx; + filp->private_data = prv; + info->vma = NULL; + + info->idx_map = kmalloc(sizeof(unsigned long) * MAX_PENDING_REQS, + GFP_KERNEL); + + if (idx > 0) { + init_waitqueue_head(&info->wait); + for (i = 0; i < MAX_PENDING_REQS; i++) + info->idx_map[i] = INVALID_REQ; + } + + DPRINTK("Tap open: device /dev/xen/blktap%d\n",idx); + return 0; + + fail_nomem: + return -ENOMEM; +} + +static int blktap_release(struct inode *inode, struct file *filp) +{ + int idx = iminor(inode) - BLKTAP_MINOR; + tap_blkif_t *info; + + if (tapfds[idx] == NULL) { + WPRINTK("Trying to free device that doesn't exist " + "[/dev/xen/blktap%d]\n",idx); + return -1; + } + info = tapfds[idx]; + info->dev_inuse = 0; + DPRINTK("Freeing device [/dev/xen/blktap%d]\n",idx); + + /* Free the ring page. */ + ClearPageReserved(virt_to_page(info->ufe_ring.sring)); + free_page((unsigned long) info->ufe_ring.sring); + + /* Clear any active mappings and free foreign map table */ + if (info->vma) { + zap_page_range( + info->vma, info->vma->vm_start, + info->vma->vm_end - info->vma->vm_start, NULL); + info->vma = NULL; + } + + if (filp->private_data) kfree(filp->private_data); + + if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) { + kthread_stop(info->blkif->xenblkd); + info->blkif->xenblkd = NULL; + info->status = CLEANSHUTDOWN; + } + return 0; +} + + +/* Note on mmap: + * We need to map pages to user space in a way that will allow the block + * subsystem set up direct IO to them. This couldn't be done before, because + * there isn't really a sane way to translate a user virtual address down to a + * physical address when the page belongs to another domain. + * + * My first approach was to map the page in to kernel memory, add an entry + * for it in the physical frame list (using alloc_lomem_region as in blkback) + * and then attempt to map that page up to user space. This is disallowed + * by xen though, which realizes that we don't really own the machine frame + * underlying the physical page. + * + * The new approach is to provide explicit support for this in xen linux. + * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages + * mapped from other vms. vma->vm_private_data is set up as a mapping + * from pages to actual page structs. There is a new clause in get_user_pages + * that does the right thing for this sort of mapping. + */ +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int size; + struct page **map; + int i; + private_info_t *prv; + tap_blkif_t *info; + + /*Retrieve the dev info*/ + prv = (private_info_t *)filp->private_data; + if (prv == NULL) { + WPRINTK("blktap: mmap, retrieving idx failed\n"); + return -ENOMEM; + } + info = tapfds[prv->idx]; + + vma->vm_flags |= VM_RESERVED; + vma->vm_ops = &blktap_vm_ops; + + size = vma->vm_end - vma->vm_start; + if (size != ((mmap_pages + RING_PAGES) << PAGE_SHIFT)) { + WPRINTK("you _must_ map exactly %d pages!\n", + mmap_pages + RING_PAGES); + return -EAGAIN; + } + + size >>= PAGE_SHIFT; + info->rings_vstart = vma->vm_start; + info->user_vstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT); - active_reqs_init(); - blkif_interface_init(); - blkdev_schedule_init(); + /* Map the ring pages to the start of the region and reserve it. */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (remap_pfn_range(vma, vma->vm_start, + __pa(info->ufe_ring.sring) >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot)) { + WPRINTK("Mapping user ring failed!\n"); + goto fail; + } + + /* Mark this VM as containing foreign pages, and set up mappings. */ + map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + * sizeof(struct page_struct*), + GFP_KERNEL); + if (map == NULL) { + WPRINTK("Couldn't alloc VM_FOREIGN map.\n"); + goto fail; + } + + for (i = 0; i < ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++) + map[i] = NULL; - (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); + vma->vm_private_data = map; + vma->vm_flags |= VM_FOREIGN; + + info->vma = vma; + info->ring_ok = 1; + return 0; + fail: + /* Clear any active mappings. */ + zap_page_range(vma, vma->vm_start, + vma->vm_end - vma->vm_start, NULL); - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_BLKIF_BE; - cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS; - cmsg.length = sizeof(blkif_be_driver_status_t); - be_st.status = BLKIF_DRIVER_STATUS_UP; - memcpy(cmsg.msg, &be_st, sizeof(be_st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); + return -ENOMEM; +} - DPRINTK(" tap - Userland channel init:\n"); - blktap_init(); +static int blktap_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int idx = iminor(inode) - BLKTAP_MINOR; + switch(cmd) { + case BLKTAP_IOCTL_KICK_FE: + { + /* There are fe messages to process. */ + return blktap_read_ufe_ring(idx); + } + case BLKTAP_IOCTL_SETMODE: + { + tap_blkif_t *info = tapfds[idx]; + + if ( (idx > 0) && (idx < MAX_TAP_DEV) + && (tapfds[idx] != NULL) ) + { + if (BLKTAP_MODE_VALID(arg)) { + info->mode = arg; + /* XXX: may need to flush rings here. */ + DPRINTK("blktap: set mode to %lx\n", + arg); + return 0; + } + } + return 0; + } + case BLKTAP_IOCTL_PRINT_IDXS: + { + tap_blkif_t *info = tapfds[idx]; + + if ( (idx > 0) && (idx < MAX_TAP_DEV) + && (tapfds[idx] != NULL) ) + { + printk("User Rings: \n-----------\n"); + printk("UF: rsp_cons: %2d, req_prod_prv: %2d " + "| req_prod: %2d, rsp_prod: %2d\n", + info->ufe_ring.rsp_cons, + info->ufe_ring.req_prod_pvt, + info->ufe_ring.sring->req_prod, + info->ufe_ring.sring->rsp_prod); + } + return 0; + } + case BLKTAP_IOCTL_SENDPID: + { + tap_blkif_t *info = tapfds[idx]; + + if ( (idx > 0) && (idx < MAX_TAP_DEV) + && (tapfds[idx] != NULL) ) + { + info->pid = (pid_t)arg; + DPRINTK("blktap: pid received %d\n", + info->pid); + } + return 0; + } + case BLKTAP_IOCTL_NEWINTF: + { + uint64_t val = (uint64_t)arg; + domid_translate_t *tr = (domid_translate_t *)&val; + int newdev; - DPRINTK("Blkif tap device initialized.\n"); + DPRINTK("NEWINTF Req for domid %d and bus id %d\n", + tr->domid, tr->busid); + newdev = get_next_free_dev(); + if (newdev < 1) { + WPRINTK("Error initialising /dev/xen/blktap - " + "No more devices\n"); + return -1; + } + translate_domid[newdev].domid = tr->domid; + translate_domid[newdev].busid = tr->busid; + return newdev; + } + case BLKTAP_IOCTL_FREEINTF: + { + unsigned long dev = arg; + tap_blkif_t *info = NULL; - return 0; + if ( (dev > 0) && (dev < MAX_TAP_DEV) ) info = tapfds[dev]; + + if ( (info != NULL) && (info->dev_pending) ) + info->dev_pending = 0; + return 0; + } + case BLKTAP_IOCTL_MINOR: + { + unsigned long dev = arg; + tap_blkif_t *info = NULL; + + if ( (dev > 0) && (dev < MAX_TAP_DEV) ) info = tapfds[dev]; + + if (info != NULL) return info->minor; + else return -1; + } + case BLKTAP_IOCTL_MAJOR: + return BLKTAP_DEV_MAJOR; + + case BLKTAP_QUERY_ALLOC_REQS: + { + WPRINTK("BLKTAP_QUERY_ALLOC_REQS ioctl: %d/%d\n", + alloc_pending_reqs, blkif_reqs); + return (alloc_pending_reqs/blkif_reqs) * 100; + } + } + return -ENOIOCTLCMD; } -#if 0 /* tap doesn't handle suspend/resume */ -void blkdev_suspend(void) +static unsigned int blktap_poll(struct file *file, poll_table *wait) { + private_info_t *prv; + tap_blkif_t *info; + + /*Retrieve the dev info*/ + prv = (private_info_t *)file->private_data; + if (prv == NULL) { + WPRINTK(" poll, retrieving idx failed\n"); + return 0; + } + + if (prv->idx == 0) return 0; + + info = tapfds[prv->idx]; + + poll_wait(file, &info->wait, wait); + if (info->ufe_ring.req_prod_pvt != info->ufe_ring.sring->req_prod) { + flush_tlb_all(); + RING_PUSH_REQUESTS(&info->ufe_ring); + return POLLIN | POLLRDNORM; + } + return 0; } -void blkdev_resume(void) +void blktap_kick_user(int idx) { - ctrl_msg_t cmsg; - blkif_fe_driver_status_t st; + tap_blkif_t *info; - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_BLKIF_FE; - cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS; - cmsg.length = sizeof(blkif_fe_driver_status_t); - st.status = BLKIF_DRIVER_STATUS_UP; - memcpy(cmsg.msg, &st, sizeof(st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); + if (idx == 0) return; + + info = tapfds[idx]; + + if (info != NULL) wake_up_interruptible(&info->wait); + return; } + +static int do_block_io_op(blkif_t *blkif); +static void dispatch_rw_block_io(blkif_t *blkif, + blkif_request_t *req, + pending_req_t *pending_req); +static void make_response(blkif_t *blkif, unsigned long id, + unsigned short op, int st); + +/****************************************************************** + * misc small helpers + */ +static int req_increase(void) +{ + int i, j; + struct page *page; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pending_free_lock, flags); + + ret = -EINVAL; + if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) + goto done; + +#ifdef __ia64__ + extern unsigned long alloc_empty_foreign_map_page_range( + unsigned long pages); + mmap_start[mmap_alloc].start = (unsigned long) + alloc_empty_foreign_map_page_range(mmap_pages); +#else /* ! ia64 */ + page = balloon_alloc_empty_page_range(mmap_pages); + ret = -ENOMEM; + if (page == NULL) { + printk("%s balloon_alloc_empty_page_range gave NULL\n", __FUNCTION__); + goto done; + } + + /* Pin all of the pages. */ + for (i=0; iinuse == 0) { + list_del(&req->free_list); + mmap_inuse--; + } + } + if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1); + done: + spin_unlock_irqrestore(&pending_free_lock, flags); + return; +} + +static pending_req_t* alloc_req(void) +{ + pending_req_t *req = NULL; + unsigned long flags; + + spin_lock_irqsave(&pending_free_lock, flags); + + if (!list_empty(&pending_free)) { + req = list_entry(pending_free.next, pending_req_t, free_list); + list_del(&req->free_list); + } + + if (req) { + req->inuse = 1; + alloc_pending_reqs++; + } + spin_unlock_irqrestore(&pending_free_lock, flags); + + return req; +} + +static void free_req(pending_req_t *req) +{ + unsigned long flags; + int was_empty; + + spin_lock_irqsave(&pending_free_lock, flags); + + alloc_pending_reqs--; + req->inuse = 0; + if (mmap_lock && (req->mem_idx == mmap_alloc-1)) { + mmap_inuse--; + if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1); + spin_unlock_irqrestore(&pending_free_lock, flags); + return; + } + was_empty = list_empty(&pending_free); + list_add(&req->free_list, &pending_free); + + spin_unlock_irqrestore(&pending_free_lock, flags); + + if (was_empty) + wake_up(&pending_free_wq); +} + +static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx, int + tapidx) +{ + struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2]; + unsigned int i, invcount = 0; + struct grant_handle_pair *khandle; + uint64_t ptep; + int ret, mmap_idx; + unsigned long kvaddr, uvaddr; + + tap_blkif_t *info = tapfds[tapidx]; + + if (info == NULL) { + WPRINTK("fast_flush: Couldn't get info!\n"); + return; + } + mmap_idx = req->mem_idx; + + for (i = 0; i < req->nr_pages; i++) { + kvaddr = MMAP_VADDR(mmap_start[mmap_idx].start, k_idx, i); + uvaddr = MMAP_VADDR(info->user_vstart, u_idx, i); + + khandle = &pending_handle(mmap_idx, k_idx, i); + if (BLKTAP_INVALID_HANDLE(khandle)) { + WPRINTK("BLKTAP_INVALID_HANDLE\n"); + continue; + } + gnttab_set_unmap_op(&unmap[invcount], + MMAP_VADDR(mmap_start[mmap_idx].start, k_idx, i), + GNTMAP_host_map, khandle->kernel); + invcount++; + + if (create_lookup_pte_addr( + info->vma->vm_mm, + MMAP_VADDR(info->user_vstart, u_idx, i), + &ptep) !=0) { + WPRINTK("Couldn't get a pte addr!\n"); + return; + } + + gnttab_set_unmap_op(&unmap[invcount], + ptep, GNTMAP_host_map, + khandle->user); + invcount++; + + BLKTAP_INVALIDATE_HANDLE(khandle); + } + ret = HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, unmap, invcount); + BUG_ON(ret); + + if (info->vma != NULL) + zap_page_range(info->vma, + MMAP_VADDR(info->user_vstart, u_idx, 0), + req->nr_pages << PAGE_SHIFT, NULL); +} + +/****************************************************************** + * SCHEDULER FUNCTIONS + */ + +static void print_stats(blkif_t *blkif) +{ + printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d\n", + current->comm, blkif->st_oo_req, + blkif->st_rd_req, blkif->st_wr_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; +} + +int tap_blkif_schedule(void *arg) +{ + blkif_t *blkif = arg; + + blkif_get(blkif); + + if (debug_lvl) + printk(KERN_DEBUG "%s: started\n", current->comm); + + while (!kthread_should_stop()) { + wait_event_interruptible( + blkif->wq, + blkif->waiting_reqs || kthread_should_stop()); + wait_event_interruptible( + pending_free_wq, + !list_empty(&pending_free) || kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ + + if (do_block_io_op(blkif)) + blkif->waiting_reqs = 1; + + if (log_stats && time_after(jiffies, blkif->st_print)) + print_stats(blkif); + } + + if (log_stats) + print_stats(blkif); + if (debug_lvl) + printk(KERN_DEBUG "%s: exiting\n", current->comm); + + blkif->xenblkd = NULL; + blkif_put(blkif); + + return 0; +} + +/****************************************************************** + * COMPLETION CALLBACK -- Called by user level ioctl() + */ + +static int blktap_read_ufe_ring(int idx) +{ + /* This is called to read responses from the UFE ring. */ + RING_IDX i, j, rp; + blkif_response_t *resp; + blkif_t *blkif=NULL; + int pending_idx, usr_idx, mmap_idx; + pending_req_t *pending_req; + tap_blkif_t *info; + + info = tapfds[idx]; + if (info == NULL) { + return 0; + } + + /* We currently only forward packets in INTERCEPT_FE mode. */ + if (!(info->mode & BLKTAP_MODE_INTERCEPT_FE)) + return 0; + + /* for each outstanding message on the UFEring */ + rp = info->ufe_ring.sring->rsp_prod; + rmb(); + + for (i = info->ufe_ring.rsp_cons; i != rp; i++) { + resp = RING_GET_RESPONSE(&info->ufe_ring, i); + ++info->ufe_ring.rsp_cons; + + /*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/ + usr_idx = (int)resp->id; + pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx])); + mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]); + + if ( (mmap_idx >= mmap_alloc) || + (ID_TO_IDX(info->idx_map[usr_idx]) >= MAX_PENDING_REQS) ) + WPRINTK("Incorrect req map" + "[%d], internal map [%d,%d (%d)]\n", + usr_idx, mmap_idx, + ID_TO_IDX(info->idx_map[usr_idx]), + MASK_PEND_IDX( + ID_TO_IDX(info->idx_map[usr_idx]))); + + pending_req = &pending_reqs[mmap_idx][pending_idx]; + blkif = pending_req->blkif; + + for (j = 0; j < pending_req->nr_pages; j++) { + + unsigned long kvaddr, uvaddr; + struct page **map = info->vma->vm_private_data; + struct page *pg; + int offset; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, j); + kvaddr = MMAP_VADDR(mmap_start[mmap_idx].start, + pending_idx, j); + + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + ClearPageReserved(pg); + offset = (uvaddr - info->vma->vm_start) + >> PAGE_SHIFT; + map[offset] = NULL; + } + fast_flush_area(pending_req, pending_idx, usr_idx, idx); + make_response(blkif, pending_req->id, resp->operation, + resp->status); + info->idx_map[usr_idx] = INVALID_REQ; + blkif_put(pending_req->blkif); + free_req(pending_req); + } + + return 0; +} + + +/****************************************************************************** + * NOTIFICATION FROM GUEST OS. + */ + +static void blkif_notify_work(blkif_t *blkif) +{ + blkif->waiting_reqs = 1; + wake_up(&blkif->wq); +} + +irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) +{ + blkif_notify_work(dev_id); + return IRQ_HANDLED; +} + + + +/****************************************************************** + * DOWNWARD CALLS -- These interface with the block-device layer proper. + */ +static int print_dbug = 1; +static int do_block_io_op(blkif_t *blkif) +{ + blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_request_t *req; + pending_req_t *pending_req; + RING_IDX rc, rp; + int more_to_do = 0; + tap_blkif_t *info; + + rc = blk_ring->req_cons; + rp = blk_ring->sring->req_prod; + rmb(); /* Ensure we see queued requests up to 'rp'. */ + + /*Check blkif has corresponding UE ring*/ + if (blkif->dev_num == -1) { + /*oops*/ + if (print_dbug) { + WPRINTK("Corresponding UE " + "ring does not exist!\n"); + print_dbug = 0; /*We only print this message once*/ + } + return 1; + } + + info = tapfds[blkif->dev_num]; + if (info == NULL || !info->dev_inuse) { + if (print_dbug) { + WPRINTK("Can't get UE info!\n"); + print_dbug = 0; + } + return 1; + } + + while (rc != rp) { + + if (RING_FULL(&info->ufe_ring)) { + WPRINTK("RING_FULL! More to do\n"); + more_to_do = 1; + break; + } + + if (RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) { + WPRINTK("RING_REQUEST_CONS_OVERFLOW!" + " More to do\n"); + more_to_do = 1; + break; + } + + pending_req = alloc_req(); + if (NULL == pending_req) { + blkif->st_oo_req++; + more_to_do = 1; + break; + } + + req = RING_GET_REQUEST(blk_ring, rc); + blk_ring->req_cons = ++rc; /* before make_response() */ + + switch (req->operation) { + case BLKIF_OP_READ: + blkif->st_rd_req++; + dispatch_rw_block_io(blkif, req, pending_req); + break; + + case BLKIF_OP_WRITE: + blkif->st_wr_req++; + dispatch_rw_block_io(blkif, req, pending_req); + break; + + default: + WPRINTK("unknown operation [%d]\n", + req->operation); + make_response(blkif, req->id, req->operation, + BLKIF_RSP_ERROR); + free_req(pending_req); + break; + } + } + + blktap_kick_user(blkif->dev_num); + + return more_to_do; +} + +static void dispatch_rw_block_io(blkif_t *blkif, + blkif_request_t *req, + pending_req_t *pending_req) +{ + extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); + int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ; + struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2]; + unsigned int nseg; + int ret, i; + tap_blkif_t *info = tapfds[blkif->dev_num]; + uint64_t sector; + + blkif_request_t *target; + int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx); + int usr_idx = GET_NEXT_REQ(info->idx_map); + uint16_t mmap_idx = pending_req->mem_idx; + + /*Check we have space on user ring - should never fail*/ + if(usr_idx == INVALID_REQ) goto fail_flush; + + /* Check that number of segments is sane. */ + nseg = req->nr_segments; + if ( unlikely(nseg == 0) || + unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) ) { + WPRINTK("Bad number of segments in request (%d)\n", nseg); + goto fail_response; + } + + /* Make sure userspace is ready. */ + if (!info->ring_ok) { + WPRINTK("blktap: ring not ready for requests!\n"); + goto fail_response; + } + + if (RING_FULL(&info->ufe_ring)) { + WPRINTK("blktap: fe_ring is full, can't add " + "IO Request will be dropped. %d %d\n", + RING_SIZE(&info->ufe_ring), + RING_SIZE(&blkif->blk_ring)); + goto fail_response; + } + + pending_req->blkif = blkif; + pending_req->id = req->id; + pending_req->operation = operation; + pending_req->status = BLKIF_RSP_OKAY; + pending_req->nr_pages = nseg; + op = 0; + for (i = 0; i < nseg; i++) { + unsigned long uvaddr; + unsigned long kvaddr; + uint64_t ptep; + struct page *page; + uint32_t flags; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i); + kvaddr = MMAP_VADDR(mmap_start[mmap_idx].start, + pending_idx, i); + page = virt_to_page(kvaddr); + + sector = req->sector_number + (8*i); + if( (blkif->sectors > 0) && (sector >= blkif->sectors) ) { + WPRINTK("BLKTAP: Sector request greater" + "than size\n"); + WPRINTK("BLKTAP: %s request sector" + "[%llu,%llu], Total [%llu]\n", + (req->operation == + BLKIF_OP_WRITE ? "WRITE" : "READ"), + (long long unsigned) sector, + (long long unsigned) sector>>9, + blkif->sectors); + } + + flags = GNTMAP_host_map; + if (operation == WRITE) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], kvaddr, flags, + req->seg[i].gref, blkif->domid); + op++; + + /* Now map it to user. */ + ret = create_lookup_pte_addr(info->vma->vm_mm, + uvaddr, &ptep); + if (ret) { + WPRINTK("Couldn't get a pte addr!\n"); + fast_flush_area(pending_req, pending_idx, usr_idx, + blkif->dev_num); + goto fail_flush; + } + + flags = GNTMAP_host_map | GNTMAP_application_map + | GNTMAP_contains_pte; + if (operation == WRITE) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], ptep, flags, + req->seg[i].gref, blkif->domid); + op++; + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op); + BUG_ON(ret); + + for (i = 0; i < (nseg*2); i+=2) { + unsigned long uvaddr; + unsigned long kvaddr; + unsigned long offset; + struct page *pg; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2); + kvaddr = MMAP_VADDR(mmap_start[mmap_idx].start, + pending_idx, i/2); + + if (unlikely(map[i].status != 0)) { + WPRINTK("invalid kernel buffer -- " + "could not remap it\n"); + goto fail_flush; + } + + if (unlikely(map[i+1].status != 0)) { + WPRINTK("invalid user buffer -- " + "could not remap it\n"); + goto fail_flush; + } + + pending_handle(mmap_idx, pending_idx, i/2).kernel + = map[i].handle; + pending_handle(mmap_idx, pending_idx, i/2).user + = map[i+1].handle; + set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, + FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); + offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + ((struct page **)info->vma->vm_private_data)[offset] = + pg; + } + /* Mark mapped pages as reserved: */ + for (i = 0; i < req->nr_segments; i++) { + unsigned long kvaddr; + struct page *pg; + + kvaddr = MMAP_VADDR(mmap_start[mmap_idx].start, + pending_idx, i); + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + SetPageReserved(pg); + } + + /*record [mmap_idx,pending_idx] to [usr_idx] mapping*/ + info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx); + + blkif_get(blkif); + /* Finally, write the request message to the user ring. */ + target = RING_GET_REQUEST(&info->ufe_ring, + info->ufe_ring.req_prod_pvt); + memcpy(target, req, sizeof(*req)); + target->id = usr_idx; + info->ufe_ring.req_prod_pvt++; + return; + + fail_flush: + WPRINTK("Reached Fail_flush\n"); + fast_flush_area(pending_req, pending_idx, usr_idx, blkif->dev_num); + fail_response: + make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + free_req(pending_req); +} + + + +/****************************************************************** + * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING + */ + + +static void make_response(blkif_t *blkif, unsigned long id, + unsigned short op, int st) +{ + blkif_response_t *resp; + unsigned long flags; + blkif_back_ring_t *blk_ring = &blkif->blk_ring; + int more_to_do = 0; + int notify; + + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + /* Place on the response ring for the relevant domain. */ + resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); + resp->id = id; + resp->operation = op; + resp->status = st; + blk_ring->rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify); + + if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) { + /* + * Tail check for pending requests. Allows frontend to avoid + * notifications if requests are already in flight (lower + * overheads and promotes batching). + */ + RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do); + } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) { + more_to_do = 1; + + } + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); + if (more_to_do) + blkif_notify_work(blkif); + if (notify) + notify_remote_via_irq(blkif->irq); +} + +static int __init blkif_init(void) +{ + int i,ret,blktap_dir; + tap_blkif_t *info; + + if (!is_running_on_xen()) + return -ENODEV; + + INIT_LIST_HEAD(&pending_free); + for(i = 0; i < 2; i++) { + ret = req_increase(); + if (ret) + break; + } + if (i == 0) + return ret; + + tap_blkif_interface_init(); + + alloc_pending_reqs = 0; + + tap_blkif_xenbus_init(); + + /*Create the blktap devices, but do not map memory or waitqueue*/ + for(i = 0; i < MAX_TAP_DEV; i++) translate_domid[i].domid = 0xFFFF; + + ret = register_chrdev(BLKTAP_DEV_MAJOR,"blktap",&blktap_fops); + blktap_dir = devfs_mk_dir(NULL, "xen", 0, NULL); + + if ( (ret < 0)||(blktap_dir < 0) ) { + WPRINTK("Couldn't register /dev/xen/blktap\n"); + return -ENOMEM; + } + + for(i = 0; i < MAX_TAP_DEV; i++ ) { + info = tapfds[i] = kzalloc(sizeof(tap_blkif_t),GFP_KERNEL); + if(tapfds[i] == NULL) return -ENOMEM; + info->minor = i; + info->pid = 0; + info->blkif = NULL; + + ret = devfs_mk_cdev(MKDEV(BLKTAP_DEV_MAJOR, i), + S_IFCHR|S_IRUGO|S_IWUSR, "xen/blktap%d", i); + + if(ret != 0) return -ENOMEM; + info->dev_pending = info->dev_inuse = 0; + + DPRINTK("Created misc_dev [/dev/xen/blktap%d]\n",i); + } + + DPRINTK("Blktap device successfully created\n"); + + return 0; +} + +module_init(blkif_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/console/Makefile b/drivers/xen/console/Makefile index e4ffdeffc..35de3e933 100644 --- a/drivers/xen/console/Makefile +++ b/drivers/xen/console/Makefile @@ -1,2 +1,2 @@ -obj-y := console.o +obj-y := console.o xencons_ring.o diff --git a/drivers/xen/console/console.c b/drivers/xen/console/console.c index 142ca2baa..ec7dd9e58 100644 --- a/drivers/xen/console/console.c +++ b/drivers/xen/console/console.c @@ -5,8 +5,11 @@ * * Copyright (c) 2002-2004, K A Fraser. * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without @@ -45,13 +48,15 @@ #include #include #include +#include #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* * Modes: @@ -66,33 +71,39 @@ static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT; static int xc_num = -1; +#ifdef CONFIG_MAGIC_SYSRQ +static unsigned long sysrq_requested; +extern int sysrq_enabled; +#endif + static int __init xencons_setup(char *str) { - char *q; - int n; - - if ( !strncmp(str, "ttyS", 4) ) - xc_mode = XC_SERIAL; - else if ( !strncmp(str, "tty", 3) ) - xc_mode = XC_TTY; - else if ( !strncmp(str, "off", 3) ) - xc_mode = XC_OFF; - - switch ( xc_mode ) - { - case XC_SERIAL: - n = simple_strtol( str+4, &q, 10 ); - if ( q > (str + 4) ) xc_num = n; - break; - case XC_TTY: - n = simple_strtol( str+3, &q, 10 ); - if ( q > (str + 3) ) xc_num = n; - break; - default: - break; - } - - return 1; + char *q; + int n; + + if (!strncmp(str, "ttyS", 4)) + xc_mode = XC_SERIAL; + else if (!strncmp(str, "tty", 3)) + xc_mode = XC_TTY; + else if (!strncmp(str, "off", 3)) + xc_mode = XC_OFF; + + switch (xc_mode) { + case XC_SERIAL: + n = simple_strtol(str+4, &q, 10); + if (q > (str + 4)) + xc_num = n; + break; + case XC_TTY: + n = simple_strtol(str+3, &q, 10); + if (q > (str + 3)) + xc_num = n; + break; + default: + break; + } + + return 1; } __setup("xencons=", xencons_setup); @@ -104,210 +115,158 @@ static unsigned int wc, wp; /* write_cons, write_prod */ static int __init xencons_bufsz_setup(char *str) { - unsigned int goal; - goal = simple_strtoul(str, NULL, 0); - while ( wbuf_size < goal ) - wbuf_size <<= 1; - return 1; + unsigned int goal; + goal = simple_strtoul(str, NULL, 0); + if (goal) { + goal = roundup_pow_of_two(goal); + if (wbuf_size < goal) + wbuf_size = goal; + } + return 1; } __setup("xencons_bufsz=", xencons_bufsz_setup); /* This lock protects accesses to the common transmit buffer. */ -static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(xencons_lock); /* Common transmit-kick routine. */ static void __xencons_tx_flush(void); -/* This task is used to defer sending console data until there is space. */ -static void xencons_tx_flush_task_routine(void *data); - -static DECLARE_TQUEUE(xencons_tx_flush_task, - xencons_tx_flush_task_routine, - NULL); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static struct tty_driver *xencons_driver; -#else -static struct tty_driver xencons_driver; -#endif - /******************** Kernel console driver ********************************/ -static void kcons_write( - struct console *c, const char *s, unsigned int count) +static void kcons_write(struct console *c, const char *s, unsigned int count) { - int i; - unsigned long flags; - - spin_lock_irqsave(&xencons_lock, flags); - - for ( i = 0; i < count; i++ ) - { - if ( (wp - wc) >= (wbuf_size - 1) ) - break; - if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' ) - wbuf[WBUF_MASK(wp++)] = '\r'; - } - - __xencons_tx_flush(); - - spin_unlock_irqrestore(&xencons_lock, flags); + int i = 0; + unsigned long flags; + + spin_lock_irqsave(&xencons_lock, flags); + + while (i < count) { + for (; i < count; i++) { + if ((wp - wc) >= (wbuf_size - 1)) + break; + if ((wbuf[WBUF_MASK(wp++)] = s[i]) == '\n') + wbuf[WBUF_MASK(wp++)] = '\r'; + } + + __xencons_tx_flush(); + } + + spin_unlock_irqrestore(&xencons_lock, flags); } -static void kcons_write_dom0( - struct console *c, const char *s, unsigned int count) +static void kcons_write_dom0(struct console *c, const char *s, unsigned int count) { - int rc; - - while ( (count > 0) && - ((rc = HYPERVISOR_console_io( - CONSOLEIO_write, count, (char *)s)) > 0) ) - { - count -= rc; - s += rc; - } + + while (count > 0) { + int rc; + rc = HYPERVISOR_console_io( CONSOLEIO_write, count, (char *)s); + if (rc <= 0) + break; + count -= rc; + s += rc; + } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static struct tty_driver *kcons_device(struct console *c, int *index) { - *index = c->index; - return xencons_driver; -} -#else -static kdev_t kcons_device(struct console *c) -{ - return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1); + *index = 0; + return xencons_driver; } -#endif static struct console kcons_info = { - device: kcons_device, - flags: CON_PRINTBUFFER, - index: -1 + .device = kcons_device, + .flags = CON_PRINTBUFFER | CON_ENABLED, + .index = -1, }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #define __RETCODE 0 static int __init xen_console_init(void) -#else -#define __RETCODE -void xen_console_init(void) -#endif { - if ( xen_start_info.flags & SIF_INITDOMAIN ) - { - if ( xc_mode == XC_DEFAULT ) - xc_mode = XC_SERIAL; - kcons_info.write = kcons_write_dom0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - if ( xc_mode == XC_SERIAL ) - kcons_info.flags |= CON_ENABLED; -#endif - } - else - { - if ( xc_mode == XC_DEFAULT ) - xc_mode = XC_TTY; - kcons_info.write = kcons_write; - } - - switch ( xc_mode ) - { - case XC_SERIAL: - strcpy(kcons_info.name, "ttyS"); - if ( xc_num == -1 ) xc_num = 0; - break; - - case XC_TTY: - strcpy(kcons_info.name, "tty"); - if ( xc_num == -1 ) xc_num = 1; - break; - - default: - return __RETCODE; - } - - wbuf = alloc_bootmem(wbuf_size); - - register_console(&kcons_info); - - return __RETCODE; + if (!is_running_on_xen()) + return __RETCODE; + + if (xen_start_info->flags & SIF_INITDOMAIN) { + if (xc_mode == XC_DEFAULT) + xc_mode = XC_SERIAL; + kcons_info.write = kcons_write_dom0; + } else { + if (xc_mode == XC_DEFAULT) + xc_mode = XC_TTY; + kcons_info.write = kcons_write; + } + + switch (xc_mode) { + case XC_SERIAL: + strcpy(kcons_info.name, "ttyS"); + if (xc_num == -1) + xc_num = 0; + break; + + case XC_TTY: + strcpy(kcons_info.name, "tty"); + if (xc_num == -1) + xc_num = 1; + break; + + default: + return __RETCODE; + } + + wbuf = alloc_bootmem(wbuf_size); + + register_console(&kcons_info); + + return __RETCODE; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) console_initcall(xen_console_init); -#endif /*** Useful function for console debugging -- goes straight to Xen. ***/ asmlinkage int xprintk(const char *fmt, ...) { - va_list args; - int printk_len; - static char printk_buf[1024]; - - /* Emit the output into the temporary buffer */ - va_start(args, fmt); - printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); - va_end(args); - - /* Send the processed output directly to Xen. */ - kcons_write_dom0(NULL, printk_buf, printk_len); - - return 0; + va_list args; + int printk_len; + static char printk_buf[1024]; + + /* Emit the output into the temporary buffer */ + va_start(args, fmt); + printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); + va_end(args); + + /* Send the processed output directly to Xen. */ + kcons_write_dom0(NULL, printk_buf, printk_len); + + return 0; } /*** Forcibly flush console data before dying. ***/ void xencons_force_flush(void) { - ctrl_msg_t msg; - int sz; - - /* Emergency console is synchronous, so there's nothing to flush. */ - if ( xen_start_info.flags & SIF_INITDOMAIN ) - return; - - /* - * We use dangerous control-interface functions that require a quiescent - * system and no interrupts. Try to ensure this with a global cli(). - */ - local_irq_disable(); /* XXXsmp */ - - /* Spin until console data is flushed through to the domain controller. */ - while ( (wc != wp) && !ctrl_if_transmitter_empty() ) - { - /* Interrupts are disabled -- we must manually reap responses. */ - ctrl_if_discard_responses(); - - if ( (sz = wp - wc) == 0 ) - continue; - if ( sz > sizeof(msg.msg) ) - sz = sizeof(msg.msg); - if ( sz > (wbuf_size - WBUF_MASK(wc)) ) - sz = wbuf_size - WBUF_MASK(wc); - - msg.type = CMSG_CONSOLE; - msg.subtype = CMSG_CONSOLE_DATA; - msg.length = sz; - memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz); - - if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 ) - wc += sz; - } + int sz; + + /* Emergency console is synchronous, so there's nothing to flush. */ + if (xen_start_info->flags & SIF_INITDOMAIN) + return; + + /* Spin until console data is flushed through to the daemon. */ + while (wc != wp) { + int sent = 0; + if ((sz = wp - wc) == 0) + continue; + sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz); + if (sent > 0) + wc += sent; + } } /******************** User-space console driver (/dev/console) ************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #define DRV(_d) (_d) -#define TTY_INDEX(_tty) ((_tty)->index) -#else -static int xencons_refcount; -static struct tty_struct *xencons_table[MAX_NR_CONSOLES]; -#define DRV(_d) (&(_d)) -#define TTY_INDEX(_tty) (MINOR((_tty)->device) - xencons_driver.minor_start) -#endif +#define DUMMY_TTY(_tty) ((xc_mode != XC_SERIAL) && \ + ((_tty)->index != (xc_num - 1))) static struct termios *xencons_termios[MAX_NR_CONSOLES]; static struct termios *xencons_termios_locked[MAX_NR_CONSOLES]; @@ -315,497 +274,371 @@ static struct tty_struct *xencons_tty; static int xencons_priv_irq; static char x_char; -/* Non-privileged receive callback. */ -static void xencons_rx(ctrl_msg_t *msg, unsigned long id) +void xencons_rx(char *buf, unsigned len, struct pt_regs *regs) { - int i; - unsigned long flags; - - spin_lock_irqsave(&xencons_lock, flags); - if ( xencons_tty != NULL ) - { - for ( i = 0; i < msg->length; i++ ) - tty_insert_flip_char(xencons_tty, msg->msg[i], 0); - tty_flip_buffer_push(xencons_tty); - } - spin_unlock_irqrestore(&xencons_lock, flags); - - msg->length = 0; - ctrl_if_send_response(msg); + int i; + unsigned long flags; + + spin_lock_irqsave(&xencons_lock, flags); + if (xencons_tty == NULL) + goto out; + + for (i = 0; i < len; i++) { +#ifdef CONFIG_MAGIC_SYSRQ + if (sysrq_enabled) { + if (buf[i] == '\x0f') { /* ^O */ + sysrq_requested = jiffies; + continue; /* don't print the sysrq key */ + } else if (sysrq_requested) { + unsigned long sysrq_timeout = + sysrq_requested + HZ*2; + sysrq_requested = 0; + if (time_before(jiffies, sysrq_timeout)) { + spin_unlock_irqrestore( + &xencons_lock, flags); + handle_sysrq( + buf[i], regs, xencons_tty); + spin_lock_irqsave( + &xencons_lock, flags); + continue; + } + } + } +#endif + tty_insert_flip_char(xencons_tty, buf[i], 0); + } + tty_flip_buffer_push(xencons_tty); + + out: + spin_unlock_irqrestore(&xencons_lock, flags); } -/* Privileged and non-privileged transmit worker. */ static void __xencons_tx_flush(void) { - int sz, work_done = 0; - ctrl_msg_t msg; - - if ( xen_start_info.flags & SIF_INITDOMAIN ) - { - if ( x_char ) - { - kcons_write_dom0(NULL, &x_char, 1); - x_char = 0; - work_done = 1; - } - - while ( wc != wp ) - { - sz = wp - wc; - if ( sz > (wbuf_size - WBUF_MASK(wc)) ) - sz = wbuf_size - WBUF_MASK(wc); - kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz); - wc += sz; - work_done = 1; - } - } - else - { - while ( x_char ) - { - msg.type = CMSG_CONSOLE; - msg.subtype = CMSG_CONSOLE_DATA; - msg.length = 1; - msg.msg[0] = x_char; - - if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 ) - x_char = 0; - else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) ) - break; - - work_done = 1; - } - - while ( wc != wp ) - { - sz = wp - wc; - if ( sz > sizeof(msg.msg) ) - sz = sizeof(msg.msg); - if ( sz > (wbuf_size - WBUF_MASK(wc)) ) - sz = wbuf_size - WBUF_MASK(wc); - - msg.type = CMSG_CONSOLE; - msg.subtype = CMSG_CONSOLE_DATA; - msg.length = sz; - memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz); - - if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 ) - wc += sz; - else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) ) - break; - - work_done = 1; - } - } - - if ( work_done && (xencons_tty != NULL) ) - { - wake_up_interruptible(&xencons_tty->write_wait); - if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - (xencons_tty->ldisc.write_wakeup != NULL) ) - (xencons_tty->ldisc.write_wakeup)(xencons_tty); - } + int sent, sz, work_done = 0; + + if (x_char) { + if (xen_start_info->flags & SIF_INITDOMAIN) + kcons_write_dom0(NULL, &x_char, 1); + else + while (x_char) + if (xencons_ring_send(&x_char, 1) == 1) + break; + x_char = 0; + work_done = 1; + } + + while (wc != wp) { + sz = wp - wc; + if (sz > (wbuf_size - WBUF_MASK(wc))) + sz = wbuf_size - WBUF_MASK(wc); + if (xen_start_info->flags & SIF_INITDOMAIN) { + kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz); + wc += sz; + } else { + sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz); + if (sent == 0) + break; + wc += sent; + } + work_done = 1; + } + + if (work_done && (xencons_tty != NULL)) { + wake_up_interruptible(&xencons_tty->write_wait); + if ((xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + (xencons_tty->ldisc.write_wakeup != NULL)) + (xencons_tty->ldisc.write_wakeup)(xencons_tty); + } } -/* Non-privileged transmit kicker. */ -static void xencons_tx_flush_task_routine(void *data) +void xencons_tx(void) { - unsigned long flags; - spin_lock_irqsave(&xencons_lock, flags); - __xencons_tx_flush(); - spin_unlock_irqrestore(&xencons_lock, flags); + unsigned long flags; + + spin_lock_irqsave(&xencons_lock, flags); + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); } /* Privileged receive callback and transmit kicker. */ static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id, - struct pt_regs *regs) + struct pt_regs *regs) { - static char rbuf[16]; - int i, l; - unsigned long flags; + static char rbuf[16]; + int l; - spin_lock_irqsave(&xencons_lock, flags); + while ((l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0) + xencons_rx(rbuf, l, regs); - if ( xencons_tty != NULL ) - { - /* Receive work. */ - while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 ) - for ( i = 0; i < l; i++ ) - tty_insert_flip_char(xencons_tty, rbuf[i], 0); - if ( xencons_tty->flip.count != 0 ) - tty_flip_buffer_push(xencons_tty); - } + xencons_tx(); - /* Transmit work. */ - __xencons_tx_flush(); - - spin_unlock_irqrestore(&xencons_lock, flags); - - return IRQ_HANDLED; + return IRQ_HANDLED; } static int xencons_write_room(struct tty_struct *tty) { - return wbuf_size - (wp - wc); + return wbuf_size - (wp - wc); } static int xencons_chars_in_buffer(struct tty_struct *tty) { - return wp - wc; + return wp - wc; } static void xencons_send_xchar(struct tty_struct *tty, char ch) { - unsigned long flags; + unsigned long flags; - if ( TTY_INDEX(tty) != 0 ) - return; + if (DUMMY_TTY(tty)) + return; - spin_lock_irqsave(&xencons_lock, flags); - x_char = ch; - __xencons_tx_flush(); - spin_unlock_irqrestore(&xencons_lock, flags); + spin_lock_irqsave(&xencons_lock, flags); + x_char = ch; + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); } static void xencons_throttle(struct tty_struct *tty) { - if ( TTY_INDEX(tty) != 0 ) - return; + if (DUMMY_TTY(tty)) + return; - if ( I_IXOFF(tty) ) - xencons_send_xchar(tty, STOP_CHAR(tty)); + if (I_IXOFF(tty)) + xencons_send_xchar(tty, STOP_CHAR(tty)); } static void xencons_unthrottle(struct tty_struct *tty) { - if ( TTY_INDEX(tty) != 0 ) - return; - - if ( I_IXOFF(tty) ) - { - if ( x_char != 0 ) - x_char = 0; - else - xencons_send_xchar(tty, START_CHAR(tty)); - } + if (DUMMY_TTY(tty)) + return; + + if (I_IXOFF(tty)) { + if (x_char != 0) + x_char = 0; + else + xencons_send_xchar(tty, START_CHAR(tty)); + } } static void xencons_flush_buffer(struct tty_struct *tty) { - unsigned long flags; + unsigned long flags; - if ( TTY_INDEX(tty) != 0 ) - return; + if (DUMMY_TTY(tty)) + return; - spin_lock_irqsave(&xencons_lock, flags); - wc = wp = 0; - spin_unlock_irqrestore(&xencons_lock, flags); + spin_lock_irqsave(&xencons_lock, flags); + wc = wp = 0; + spin_unlock_irqrestore(&xencons_lock, flags); } static inline int __xencons_put_char(int ch) { - char _ch = (char)ch; - if ( (wp - wc) == wbuf_size ) - return 0; - wbuf[WBUF_MASK(wp++)] = _ch; - return 1; + char _ch = (char)ch; + if ((wp - wc) == wbuf_size) + return 0; + wbuf[WBUF_MASK(wp++)] = _ch; + return 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static int xencons_write( - struct tty_struct *tty, - const unsigned char *buf, - int count) + struct tty_struct *tty, + const unsigned char *buf, + int count) { - int i; - unsigned long flags; + int i; + unsigned long flags; - if ( TTY_INDEX(tty) != 0 ) - return count; + if (DUMMY_TTY(tty)) + return count; - spin_lock_irqsave(&xencons_lock, flags); + spin_lock_irqsave(&xencons_lock, flags); - for ( i = 0; i < count; i++ ) - if ( !__xencons_put_char(buf[i]) ) - break; + for (i = 0; i < count; i++) + if (!__xencons_put_char(buf[i])) + break; - if ( i != 0 ) - __xencons_tx_flush(); + if (i != 0) + __xencons_tx_flush(); - spin_unlock_irqrestore(&xencons_lock, flags); + spin_unlock_irqrestore(&xencons_lock, flags); - return i; + return i; } -#else -static int xencons_write( - struct tty_struct *tty, - int from_user, - const u_char *buf, - int count) -{ - int i; - unsigned long flags; - - if ( from_user && verify_area(VERIFY_READ, buf, count) ) - return -EINVAL; - - if ( TTY_INDEX(tty) != 0 ) - return count; - - spin_lock_irqsave(&xencons_lock, flags); - - for ( i = 0; i < count; i++ ) - { - char ch; - if ( from_user ) - __get_user(ch, buf + i); - else - ch = buf[i]; - if ( !__xencons_put_char(ch) ) - break; - } - - if ( i != 0 ) - __xencons_tx_flush(); - - spin_unlock_irqrestore(&xencons_lock, flags); - - return i; -} -#endif static void xencons_put_char(struct tty_struct *tty, u_char ch) { - unsigned long flags; + unsigned long flags; - if ( TTY_INDEX(tty) != 0 ) - return; + if (DUMMY_TTY(tty)) + return; - spin_lock_irqsave(&xencons_lock, flags); - (void)__xencons_put_char(ch); - spin_unlock_irqrestore(&xencons_lock, flags); + spin_lock_irqsave(&xencons_lock, flags); + (void)__xencons_put_char(ch); + spin_unlock_irqrestore(&xencons_lock, flags); } static void xencons_flush_chars(struct tty_struct *tty) { - unsigned long flags; + unsigned long flags; - if ( TTY_INDEX(tty) != 0 ) - return; + if (DUMMY_TTY(tty)) + return; - spin_lock_irqsave(&xencons_lock, flags); - __xencons_tx_flush(); - spin_unlock_irqrestore(&xencons_lock, flags); + spin_lock_irqsave(&xencons_lock, flags); + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); } static void xencons_wait_until_sent(struct tty_struct *tty, int timeout) { - unsigned long orig_jiffies = jiffies; - - if ( TTY_INDEX(tty) != 0 ) - return; - - while ( DRV(tty->driver)->chars_in_buffer(tty) ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - if ( signal_pending(current) ) - break; - if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) ) - break; - } - - set_current_state(TASK_RUNNING); + unsigned long orig_jiffies = jiffies; + + if (DUMMY_TTY(tty)) + return; + + while (DRV(tty->driver)->chars_in_buffer(tty)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + + set_current_state(TASK_RUNNING); } static int xencons_open(struct tty_struct *tty, struct file *filp) { - unsigned long flags; + unsigned long flags; - if ( TTY_INDEX(tty) != 0 ) - return 0; + if (DUMMY_TTY(tty)) + return 0; - spin_lock_irqsave(&xencons_lock, flags); - tty->driver_data = NULL; - if ( xencons_tty == NULL ) - xencons_tty = tty; - __xencons_tx_flush(); - spin_unlock_irqrestore(&xencons_lock, flags); + spin_lock_irqsave(&xencons_lock, flags); + tty->driver_data = NULL; + if (xencons_tty == NULL) + xencons_tty = tty; + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); - return 0; + return 0; } static void xencons_close(struct tty_struct *tty, struct file *filp) { - unsigned long flags; - - if ( TTY_INDEX(tty) != 0 ) - return; - - if ( tty->count == 1 ) - { - tty->closing = 1; - tty_wait_until_sent(tty, 0); - if ( DRV(tty->driver)->flush_buffer != NULL ) - DRV(tty->driver)->flush_buffer(tty); - if ( tty->ldisc.flush_buffer != NULL ) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - spin_lock_irqsave(&xencons_lock, flags); - xencons_tty = NULL; - spin_unlock_irqrestore(&xencons_lock, flags); - } + unsigned long flags; + + if (DUMMY_TTY(tty)) + return; + + mutex_lock(&tty_mutex); + + if (tty->count != 1) { + mutex_unlock(&tty_mutex); + return; + } + + /* Prevent other threads from re-opening this tty. */ + set_bit(TTY_CLOSING, &tty->flags); + mutex_unlock(&tty_mutex); + + tty->closing = 1; + tty_wait_until_sent(tty, 0); + if (DRV(tty->driver)->flush_buffer != NULL) + DRV(tty->driver)->flush_buffer(tty); + if (tty->ldisc.flush_buffer != NULL) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + spin_lock_irqsave(&xencons_lock, flags); + xencons_tty = NULL; + spin_unlock_irqrestore(&xencons_lock, flags); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static struct tty_operations xencons_ops = { - .open = xencons_open, - .close = xencons_close, - .write = xencons_write, - .write_room = xencons_write_room, - .put_char = xencons_put_char, - .flush_chars = xencons_flush_chars, - .chars_in_buffer = xencons_chars_in_buffer, - .send_xchar = xencons_send_xchar, - .flush_buffer = xencons_flush_buffer, - .throttle = xencons_throttle, - .unthrottle = xencons_unthrottle, - .wait_until_sent = xencons_wait_until_sent, + .open = xencons_open, + .close = xencons_close, + .write = xencons_write, + .write_room = xencons_write_room, + .put_char = xencons_put_char, + .flush_chars = xencons_flush_chars, + .chars_in_buffer = xencons_chars_in_buffer, + .send_xchar = xencons_send_xchar, + .flush_buffer = xencons_flush_buffer, + .throttle = xencons_throttle, + .unthrottle = xencons_unthrottle, + .wait_until_sent = xencons_wait_until_sent, }; -#ifdef CONFIG_XEN_PRIVILEGED_GUEST -static const char *xennullcon_startup(void) -{ - return NULL; -} - -static int xennullcon_dummy(void) -{ - return 0; -} - -#define DUMMY (void *)xennullcon_dummy - -/* - * The console `switch' structure for the dummy console - * - * Most of the operations are dummies. - */ - -const struct consw xennull_con = { - .owner = THIS_MODULE, - .con_startup = xennullcon_startup, - .con_init = DUMMY, - .con_deinit = DUMMY, - .con_clear = DUMMY, - .con_putc = DUMMY, - .con_putcs = DUMMY, - .con_cursor = DUMMY, - .con_scroll = DUMMY, - .con_bmove = DUMMY, - .con_switch = DUMMY, - .con_blank = DUMMY, - .con_font_set = DUMMY, - .con_font_get = DUMMY, - .con_font_default = DUMMY, - .con_font_copy = DUMMY, - .con_set_palette = DUMMY, - .con_scrolldelta = DUMMY, -}; -#endif -#endif - static int __init xencons_init(void) { - int rc; - - if ( xc_mode == XC_OFF ) - return 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? - 1 : MAX_NR_CONSOLES); - if ( xencons_driver == NULL ) - return -ENOMEM; -#else - memset(&xencons_driver, 0, sizeof(struct tty_driver)); - xencons_driver.magic = TTY_DRIVER_MAGIC; - xencons_driver.refcount = &xencons_refcount; - xencons_driver.table = xencons_table; - xencons_driver.num = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES; -#endif - - DRV(xencons_driver)->major = TTY_MAJOR; - DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL; - DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL; - DRV(xencons_driver)->init_termios = tty_std_termios; - DRV(xencons_driver)->flags = - TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS; - DRV(xencons_driver)->termios = xencons_termios; - DRV(xencons_driver)->termios_locked = xencons_termios_locked; - - if ( xc_mode == XC_SERIAL ) - { - DRV(xencons_driver)->name = "ttyS"; - DRV(xencons_driver)->minor_start = 64 + xc_num; - DRV(xencons_driver)->name_base = 0 + xc_num; - } - else - { - DRV(xencons_driver)->name = "tty"; - DRV(xencons_driver)->minor_start = xc_num; - DRV(xencons_driver)->name_base = xc_num; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - tty_set_operations(xencons_driver, &xencons_ops); -#else - xencons_driver.open = xencons_open; - xencons_driver.close = xencons_close; - xencons_driver.write = xencons_write; - xencons_driver.write_room = xencons_write_room; - xencons_driver.put_char = xencons_put_char; - xencons_driver.flush_chars = xencons_flush_chars; - xencons_driver.chars_in_buffer = xencons_chars_in_buffer; - xencons_driver.send_xchar = xencons_send_xchar; - xencons_driver.flush_buffer = xencons_flush_buffer; - xencons_driver.throttle = xencons_throttle; - xencons_driver.unthrottle = xencons_unthrottle; - xencons_driver.wait_until_sent = xencons_wait_until_sent; -#endif - - if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 ) - { - printk("WARNING: Failed to register Xen virtual " - "console driver as '%s%d'\n", - DRV(xencons_driver)->name, DRV(xencons_driver)->name_base); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - put_tty_driver(xencons_driver); - xencons_driver = NULL; -#endif - return rc; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - tty_register_device(xencons_driver, 0, NULL); -#endif - - if ( xen_start_info.flags & SIF_INITDOMAIN ) - { - xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE); - (void)request_irq(xencons_priv_irq, - xencons_priv_interrupt, 0, "console", NULL); - } - else - { - (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0); - } - - printk("Xen virtual console successfully installed as %s%d\n", - DRV(xencons_driver)->name, - DRV(xencons_driver)->name_base ); - - return 0; + int rc; + + if (!is_running_on_xen()) + return -ENODEV; + + if (xc_mode == XC_OFF) + return 0; + + xencons_ring_init(); + + xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? + 1 : MAX_NR_CONSOLES); + if (xencons_driver == NULL) + return -ENOMEM; + + DRV(xencons_driver)->name = "xencons"; + DRV(xencons_driver)->major = TTY_MAJOR; + DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL; + DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL; + DRV(xencons_driver)->init_termios = tty_std_termios; + DRV(xencons_driver)->flags = + TTY_DRIVER_REAL_RAW | + TTY_DRIVER_RESET_TERMIOS; + DRV(xencons_driver)->termios = xencons_termios; + DRV(xencons_driver)->termios_locked = xencons_termios_locked; + + if (xc_mode == XC_SERIAL) { + DRV(xencons_driver)->name = "ttyS"; + DRV(xencons_driver)->minor_start = 64 + xc_num; + DRV(xencons_driver)->name_base = 0 + xc_num; + } else { + DRV(xencons_driver)->name = "tty"; + DRV(xencons_driver)->minor_start = 1; + DRV(xencons_driver)->name_base = 1; + } + + tty_set_operations(xencons_driver, &xencons_ops); + + if ((rc = tty_register_driver(DRV(xencons_driver))) != 0) { + printk("WARNING: Failed to register Xen virtual " + "console driver as '%s%d'\n", + DRV(xencons_driver)->name, + DRV(xencons_driver)->name_base); + put_tty_driver(xencons_driver); + xencons_driver = NULL; + return rc; + } + + if (xen_start_info->flags & SIF_INITDOMAIN) { + xencons_priv_irq = bind_virq_to_irqhandler( + VIRQ_CONSOLE, + 0, + xencons_priv_interrupt, + 0, + "console", + NULL); + BUG_ON(xencons_priv_irq < 0); + } + + printk("Xen virtual console successfully installed as %s%d\n", + DRV(xencons_driver)->name, xc_num); + + return 0; } module_init(xencons_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/evtchn/evtchn.c b/drivers/xen/evtchn/evtchn.c index f5da4283d..76bfab82e 100644 --- a/drivers/xen/evtchn/evtchn.c +++ b/drivers/xen/evtchn/evtchn.c @@ -1,13 +1,16 @@ /****************************************************************************** * evtchn.c * - * Xenolinux driver for receiving and demuxing event-channel signals. + * Driver for receiving and demuxing event-channel signals. * - * Copyright (c) 2004, K A Fraser + * Copyright (c) 2004-2005, K A Fraser * Multi-process extensions Copyright (c) 2004, Steven Smith * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without @@ -44,31 +47,20 @@ #include #include #include -#define XEN_EVTCHN_MASK_OPS -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#include -#define OLD_DEVFS -#else #include -#endif - -#ifdef OLD_DEVFS -/* NB. This must be shared amongst drivers if more things go in /dev/xen */ -static devfs_handle_t xen_dev_dir; -#endif +#include +#include struct per_user_data { - /* Notification ring, accessed via /dev/xen/evtchn. */ -# define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */ -# define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) - u16 *ring; - unsigned int ring_cons, ring_prod, ring_overflow; - - /* Processes wait on this queue when ring is empty. */ - wait_queue_head_t evtchn_wait; - struct fasync_struct *evtchn_async_queue; + /* Notification ring, accessed via /dev/xen/evtchn. */ +#define EVTCHN_RING_SIZE (PAGE_SIZE / sizeof(evtchn_port_t)) +#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) + evtchn_port_t *ring; + unsigned int ring_cons, ring_prod, ring_overflow; + + /* Processes wait on this queue when ring is empty. */ + wait_queue_head_t evtchn_wait; + struct fasync_struct *evtchn_async_queue; }; /* Who's bound to each port? */ @@ -77,354 +69,390 @@ static spinlock_t port_user_lock; void evtchn_device_upcall(int port) { - struct per_user_data *u; - - spin_lock(&port_user_lock); - - mask_evtchn(port); - clear_evtchn(port); - - if ( (u = port_user[port]) != NULL ) - { - if ( (u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE ) - { - u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port; - if ( u->ring_cons == u->ring_prod++ ) - { - wake_up_interruptible(&u->evtchn_wait); - kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN); - } - } - else - { - u->ring_overflow = 1; - } - } - - spin_unlock(&port_user_lock); + struct per_user_data *u; + + spin_lock(&port_user_lock); + + mask_evtchn(port); + clear_evtchn(port); + + if ((u = port_user[port]) != NULL) { + if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) { + u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port; + if (u->ring_cons == u->ring_prod++) { + wake_up_interruptible(&u->evtchn_wait); + kill_fasync(&u->evtchn_async_queue, + SIGIO, POLL_IN); + } + } else { + u->ring_overflow = 1; + } + } + + spin_unlock(&port_user_lock); } -static ssize_t evtchn_read(struct file *file, char *buf, - size_t count, loff_t *ppos) +static ssize_t evtchn_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) { - int rc; - unsigned int c, p, bytes1 = 0, bytes2 = 0; - DECLARE_WAITQUEUE(wait, current); - struct per_user_data *u = file->private_data; - - add_wait_queue(&u->evtchn_wait, &wait); - - count &= ~1; /* even number of bytes */ - - if ( count == 0 ) - { - rc = 0; - goto out; - } - - if ( count > PAGE_SIZE ) - count = PAGE_SIZE; - - for ( ; ; ) - { - set_current_state(TASK_INTERRUPTIBLE); - - if ( (c = u->ring_cons) != (p = u->ring_prod) ) - break; - - if ( u->ring_overflow ) - { - rc = -EFBIG; - goto out; - } - - if ( file->f_flags & O_NONBLOCK ) - { - rc = -EAGAIN; - goto out; - } - - if ( signal_pending(current) ) - { - rc = -ERESTARTSYS; - goto out; - } - - schedule(); - } - - /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ - if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) - { - bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(u16); - bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16); - } - else - { - bytes1 = (p - c) * sizeof(u16); - bytes2 = 0; - } - - /* Truncate chunks according to caller's maximum byte count. */ - if ( bytes1 > count ) - { - bytes1 = count; - bytes2 = 0; - } - else if ( (bytes1 + bytes2) > count ) - { - bytes2 = count - bytes1; - } - - if ( copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || - ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2)) ) - { - rc = -EFAULT; - goto out; - } - - u->ring_cons += (bytes1 + bytes2) / sizeof(u16); - - rc = bytes1 + bytes2; - - out: - __set_current_state(TASK_RUNNING); - remove_wait_queue(&u->evtchn_wait, &wait); - return rc; + int rc; + unsigned int c, p, bytes1 = 0, bytes2 = 0; + struct per_user_data *u = file->private_data; + + /* Whole number of ports. */ + count &= ~(sizeof(evtchn_port_t)-1); + + if (count == 0) + return 0; + + if (count > PAGE_SIZE) + count = PAGE_SIZE; + + for (;;) { + if (u->ring_overflow) + return -EFBIG; + + if ((c = u->ring_cons) != (p = u->ring_prod)) + break; + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + rc = wait_event_interruptible( + u->evtchn_wait, u->ring_cons != u->ring_prod); + if (rc) + return rc; + } + + /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ + if (((c ^ p) & EVTCHN_RING_SIZE) != 0) { + bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * + sizeof(evtchn_port_t); + bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t); + } else { + bytes1 = (p - c) * sizeof(evtchn_port_t); + bytes2 = 0; + } + + /* Truncate chunks according to caller's maximum byte count. */ + if (bytes1 > count) { + bytes1 = count; + bytes2 = 0; + } else if ((bytes1 + bytes2) > count) { + bytes2 = count - bytes1; + } + + if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || + ((bytes2 != 0) && + copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) + return -EFAULT; + + u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); + + return bytes1 + bytes2; } -static ssize_t evtchn_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) +static ssize_t evtchn_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { - int rc, i; - u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL); - struct per_user_data *u = file->private_data; + int rc, i; + evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL); + struct per_user_data *u = file->private_data; - if ( kbuf == NULL ) - return -ENOMEM; + if (kbuf == NULL) + return -ENOMEM; - count &= ~1; /* even number of bytes */ + /* Whole number of ports. */ + count &= ~(sizeof(evtchn_port_t)-1); - if ( count == 0 ) - { - rc = 0; - goto out; - } + if (count == 0) { + rc = 0; + goto out; + } - if ( count > PAGE_SIZE ) - count = PAGE_SIZE; + if (count > PAGE_SIZE) + count = PAGE_SIZE; - if ( copy_from_user(kbuf, buf, count) != 0 ) - { - rc = -EFAULT; - goto out; - } + if (copy_from_user(kbuf, buf, count) != 0) { + rc = -EFAULT; + goto out; + } - spin_lock_irq(&port_user_lock); - for ( i = 0; i < (count/2); i++ ) - if ( (kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u) ) - unmask_evtchn(kbuf[i]); - spin_unlock_irq(&port_user_lock); + spin_lock_irq(&port_user_lock); + for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) + if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u)) + unmask_evtchn(kbuf[i]); + spin_unlock_irq(&port_user_lock); - rc = count; + rc = count; out: - free_page((unsigned long)kbuf); - return rc; + free_page((unsigned long)kbuf); + return rc; } -static int evtchn_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static void evtchn_bind_to_user(struct per_user_data *u, int port) { - int rc = 0; - struct per_user_data *u = file->private_data; + spin_lock_irq(&port_user_lock); + BUG_ON(port_user[port] != NULL); + port_user[port] = u; + unmask_evtchn(port); + spin_unlock_irq(&port_user_lock); +} - spin_lock_irq(&port_user_lock); +static int evtchn_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int rc; + struct per_user_data *u = file->private_data; + void __user *uarg = (void __user *) arg; + + switch (cmd) { + case IOCTL_EVTCHN_BIND_VIRQ: { + struct ioctl_evtchn_bind_virq bind; + struct evtchn_bind_virq bind_virq; + + rc = -EFAULT; + if (copy_from_user(&bind, uarg, sizeof(bind))) + break; + + bind_virq.virq = bind.virq; + bind_virq.vcpu = 0; + rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, + &bind_virq); + if (rc != 0) + break; + + rc = bind_virq.port; + evtchn_bind_to_user(u, rc); + break; + } + + case IOCTL_EVTCHN_BIND_INTERDOMAIN: { + struct ioctl_evtchn_bind_interdomain bind; + struct evtchn_bind_interdomain bind_interdomain; + + rc = -EFAULT; + if (copy_from_user(&bind, uarg, sizeof(bind))) + break; + + bind_interdomain.remote_dom = bind.remote_domain; + bind_interdomain.remote_port = bind.remote_port; + rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, + &bind_interdomain); + if (rc != 0) + break; + + rc = bind_interdomain.local_port; + evtchn_bind_to_user(u, rc); + break; + } + + case IOCTL_EVTCHN_BIND_UNBOUND_PORT: { + struct ioctl_evtchn_bind_unbound_port bind; + struct evtchn_alloc_unbound alloc_unbound; + + rc = -EFAULT; + if (copy_from_user(&bind, uarg, sizeof(bind))) + break; + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = bind.remote_domain; + rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, + &alloc_unbound); + if (rc != 0) + break; + + rc = alloc_unbound.port; + evtchn_bind_to_user(u, rc); + break; + } + + case IOCTL_EVTCHN_UNBIND: { + struct ioctl_evtchn_unbind unbind; + struct evtchn_close close; + int ret; + + rc = -EFAULT; + if (copy_from_user(&unbind, uarg, sizeof(unbind))) + break; + + rc = -EINVAL; + if (unbind.port >= NR_EVENT_CHANNELS) + break; + + spin_lock_irq(&port_user_lock); - switch ( cmd ) - { - case EVTCHN_RESET: - /* Initialise the ring to empty. Clear errors. */ - u->ring_cons = u->ring_prod = u->ring_overflow = 0; - break; - - case EVTCHN_BIND: - if ( arg >= NR_EVENT_CHANNELS ) - { - rc = -EINVAL; - } - else if ( port_user[arg] != NULL ) - { - rc = -EISCONN; - } - else - { - port_user[arg] = u; - unmask_evtchn(arg); - } - break; - - case EVTCHN_UNBIND: - if ( arg >= NR_EVENT_CHANNELS ) - { - rc = -EINVAL; - } - else if ( port_user[arg] != u ) - { - rc = -ENOTCONN; - } - else - { - port_user[arg] = NULL; - mask_evtchn(arg); - } - break; - - default: - rc = -ENOSYS; - break; - } - - spin_unlock_irq(&port_user_lock); - - return rc; + rc = -ENOTCONN; + if (port_user[unbind.port] != u) { + spin_unlock_irq(&port_user_lock); + break; + } + + port_user[unbind.port] = NULL; + mask_evtchn(unbind.port); + + spin_unlock_irq(&port_user_lock); + + close.port = unbind.port; + ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + BUG_ON(ret); + + rc = 0; + break; + } + + case IOCTL_EVTCHN_NOTIFY: { + struct ioctl_evtchn_notify notify; + + rc = -EFAULT; + if (copy_from_user(¬ify, uarg, sizeof(notify))) + break; + + if (notify.port >= NR_EVENT_CHANNELS) { + rc = -EINVAL; + } else if (port_user[notify.port] != u) { + rc = -ENOTCONN; + } else { + notify_remote_via_evtchn(notify.port); + rc = 0; + } + break; + } + + case IOCTL_EVTCHN_RESET: { + /* Initialise the ring to empty. Clear errors. */ + spin_lock_irq(&port_user_lock); + u->ring_cons = u->ring_prod = u->ring_overflow = 0; + spin_unlock_irq(&port_user_lock); + rc = 0; + break; + } + + default: + rc = -ENOSYS; + break; + } + + return rc; } static unsigned int evtchn_poll(struct file *file, poll_table *wait) { - unsigned int mask = POLLOUT | POLLWRNORM; - struct per_user_data *u = file->private_data; - - poll_wait(file, &u->evtchn_wait, wait); - if ( u->ring_cons != u->ring_prod ) - mask |= POLLIN | POLLRDNORM; - if ( u->ring_overflow ) - mask = POLLERR; - return mask; + unsigned int mask = POLLOUT | POLLWRNORM; + struct per_user_data *u = file->private_data; + + poll_wait(file, &u->evtchn_wait, wait); + if (u->ring_cons != u->ring_prod) + mask |= POLLIN | POLLRDNORM; + if (u->ring_overflow) + mask = POLLERR; + return mask; } static int evtchn_fasync(int fd, struct file *filp, int on) { - struct per_user_data *u = filp->private_data; - return fasync_helper(fd, filp, on, &u->evtchn_async_queue); + struct per_user_data *u = filp->private_data; + return fasync_helper(fd, filp, on, &u->evtchn_async_queue); } static int evtchn_open(struct inode *inode, struct file *filp) { - struct per_user_data *u; + struct per_user_data *u; - if ( (u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL ) - return -ENOMEM; + if ((u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL) + return -ENOMEM; - memset(u, 0, sizeof(*u)); - init_waitqueue_head(&u->evtchn_wait); + memset(u, 0, sizeof(*u)); + init_waitqueue_head(&u->evtchn_wait); - if ( (u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL ) - { - kfree(u); - return -ENOMEM; - } + u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL); + if (u->ring == NULL) { + kfree(u); + return -ENOMEM; + } - filp->private_data = u; + filp->private_data = u; - return 0; + return 0; } static int evtchn_release(struct inode *inode, struct file *filp) { - int i; - struct per_user_data *u = filp->private_data; + int i; + struct per_user_data *u = filp->private_data; + struct evtchn_close close; + + spin_lock_irq(&port_user_lock); - spin_lock_irq(&port_user_lock); + free_page((unsigned long)u->ring); - free_page((unsigned long)u->ring); + for (i = 0; i < NR_EVENT_CHANNELS; i++) { + int ret; + if (port_user[i] != u) + continue; - for ( i = 0; i < NR_EVENT_CHANNELS; i++ ) - { - if ( port_user[i] == u ) - { - port_user[i] = NULL; - mask_evtchn(i); - } - } + port_user[i] = NULL; + mask_evtchn(i); - spin_unlock_irq(&port_user_lock); + close.port = i; + ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + BUG_ON(ret); + } - return 0; + spin_unlock_irq(&port_user_lock); + + kfree(u); + + return 0; } static struct file_operations evtchn_fops = { - owner: THIS_MODULE, - read: evtchn_read, - write: evtchn_write, - ioctl: evtchn_ioctl, - poll: evtchn_poll, - fasync: evtchn_fasync, - open: evtchn_open, - release: evtchn_release + .owner = THIS_MODULE, + .read = evtchn_read, + .write = evtchn_write, + .ioctl = evtchn_ioctl, + .poll = evtchn_poll, + .fasync = evtchn_fasync, + .open = evtchn_open, + .release = evtchn_release, }; static struct miscdevice evtchn_miscdev = { - .minor = EVTCHN_MINOR, - .name = "evtchn", - .fops = &evtchn_fops, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .devfs_name = "misc/evtchn", -#endif + .minor = EVTCHN_MINOR, + .name = "evtchn", + .fops = &evtchn_fops, + .devfs_name = "misc/evtchn", }; static int __init evtchn_init(void) { -#ifdef OLD_DEVFS - devfs_handle_t symlink_handle; - int pos; - char link_dest[64]; -#endif - int err; - - spin_lock_init(&port_user_lock); - memset(port_user, 0, sizeof(port_user)); - - /* (DEVFS) create '/dev/misc/evtchn'. */ - err = misc_register(&evtchn_miscdev); - if ( err != 0 ) - { - printk(KERN_ALERT "Could not register /dev/misc/evtchn\n"); - return err; - } - -#ifdef OLD_DEVFS - /* (DEVFS) create directory '/dev/xen'. */ - xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL); - - /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */ - pos = devfs_generate_path(evtchn_miscdev.devfs_handle, - &link_dest[3], - sizeof(link_dest) - 3); - if ( pos >= 0 ) - strncpy(&link_dest[pos], "../", 3); - - /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */ - (void)devfs_mk_symlink(xen_dev_dir, - "evtchn", - DEVFS_FL_DEFAULT, - &link_dest[pos], - &symlink_handle, - NULL); - - /* (DEVFS) automatically destroy the symlink with its destination. */ - devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle); -#endif - - printk("Event-channel device installed.\n"); - - return 0; + int err; + + if (!is_running_on_xen()) + return -ENODEV; + + spin_lock_init(&port_user_lock); + memset(port_user, 0, sizeof(port_user)); + + /* Create '/dev/misc/evtchn'. */ + err = misc_register(&evtchn_miscdev); + if (err != 0) { + printk(KERN_ALERT "Could not register /dev/misc/evtchn\n"); + return err; + } + + printk("Event-channel device installed.\n"); + + return 0; } static void evtchn_cleanup(void) { - misc_deregister(&evtchn_miscdev); + misc_deregister(&evtchn_miscdev); } module_init(evtchn_init); module_exit(evtchn_cleanup); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/netback/Makefile b/drivers/xen/netback/Makefile index 327944214..d5d232837 100644 --- a/drivers/xen/netback/Makefile +++ b/drivers/xen/netback/Makefile @@ -1,2 +1,5 @@ +obj-$(CONFIG_XEN_NETDEV_BACKEND) := netbk.o +obj-$(CONFIG_XEN_NETDEV_LOOPBACK) += netloop.o -obj-y := netback.o control.o interface.o +netbk-y := netback.o xenbus.o interface.o +netloop-y := loopback.o diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h index dfb750ee3..c5ec30071 100644 --- a/drivers/xen/netback/common.h +++ b/drivers/xen/netback/common.h @@ -1,5 +1,29 @@ /****************************************************************************** * arch/xen/drivers/netif/backend/common.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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ #ifndef __NETIF__BACKEND__COMMON_H__ @@ -14,84 +38,83 @@ #include #include #include -#include -#include +#include +#include +#include #include #include - -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define ASSERT(_p) ((void)0) -#define DPRINTK(_f, _a...) ((void)0) -#endif +#include +#include +#include + +#define DPRINTK(_f, _a...) \ + pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) +#define IPRINTK(fmt, args...) \ + printk(KERN_INFO "xen_net: " fmt, ##args) +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_net: " fmt, ##args) typedef struct netif_st { - /* Unique identifier for this interface. */ - domid_t domid; - unsigned int handle; - - u8 fe_dev_addr[6]; - - /* Physical parameters of the comms window. */ - unsigned long tx_shmem_frame; - unsigned long rx_shmem_frame; - unsigned int evtchn; - int irq; - - /* The shared rings and indexes. */ - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; - - /* Private indexes into shared ring. */ - NETIF_RING_IDX rx_req_cons; - NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */ - NETIF_RING_IDX tx_req_cons; - NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */ - - /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ - unsigned long credit_bytes; - unsigned long credit_usec; - unsigned long remaining_credit; - struct timer_list credit_timeout; - - /* Miscellaneous private stuff. */ - enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; - int active; - /* - * DISCONNECT response is deferred until pending requests are ack'ed. - * We therefore need to store the id from the original request. - */ - u8 disconnect_rspid; - struct netif_st *hash_next; - struct list_head list; /* scheduling list */ - atomic_t refcnt; - struct net_device *dev; - struct net_device_stats stats; - - struct work_struct work; + /* Unique identifier for this interface. */ + domid_t domid; + unsigned int handle; + + u8 fe_dev_addr[6]; + + /* Physical parameters of the comms window. */ + grant_handle_t tx_shmem_handle; + grant_ref_t tx_shmem_ref; + grant_handle_t rx_shmem_handle; + grant_ref_t rx_shmem_ref; + unsigned int evtchn; + unsigned int irq; + + /* The shared rings and indexes. */ + netif_tx_back_ring_t tx; + netif_rx_back_ring_t rx; + struct vm_struct *tx_comms_area; + struct vm_struct *rx_comms_area; + + /* Set of features that can be turned on in dev->features. */ + int features; + int can_queue; + + /* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */ + RING_IDX rx_req_cons_peek; + + /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ + unsigned long credit_bytes; + unsigned long credit_usec; + unsigned long remaining_credit; + struct timer_list credit_timeout; + + /* Miscellaneous private stuff. */ + struct list_head list; /* scheduling list */ + atomic_t refcnt; + struct net_device *dev; + struct net_device_stats stats; + + wait_queue_head_t waiting_to_free; } netif_t; -void netif_create(netif_be_create_t *create); -void netif_destroy(netif_be_destroy_t *destroy); -void netif_creditlimit(netif_be_creditlimit_t *creditlimit); -void netif_connect(netif_be_connect_t *connect); -int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id); -void netif_disconnect_complete(netif_t *netif); -netif_t *netif_find_by_handle(domid_t domid, unsigned int handle); +#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) +#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) + +void netif_disconnect(netif_t *netif); + +netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]); +int netif_map(netif_t *netif, unsigned long tx_ring_ref, + unsigned long rx_ring_ref, unsigned int evtchn); + #define netif_get(_b) (atomic_inc(&(_b)->refcnt)) -#define netif_put(_b) \ - do { \ - if ( atomic_dec_and_test(&(_b)->refcnt) ) \ - netif_disconnect_complete(_b); \ - } while (0) +#define netif_put(_b) \ + do { \ + if ( atomic_dec_and_test(&(_b)->refcnt) ) \ + wake_up(&(_b)->waiting_to_free); \ + } while (0) -void netif_interface_init(void); -void netif_ctrlif_init(void); +void netif_xenbus_init(void); void netif_schedule_work(netif_t *netif); void netif_deschedule_work(netif_t *netif); @@ -100,4 +123,16 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev); struct net_device_stats *netif_be_get_stats(struct net_device *dev); irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs); +static inline int netbk_can_queue(struct net_device *dev) +{ + netif_t *netif = netdev_priv(dev); + return netif->can_queue; +} + +static inline int netbk_can_sg(struct net_device *dev) +{ + netif_t *netif = netdev_priv(dev); + return netif->features & NETIF_F_SG; +} + #endif /* __NETIF__BACKEND__COMMON_H__ */ diff --git a/drivers/xen/netback/interface.c b/drivers/xen/netback/interface.c index f509a1b8d..d60b23b0f 100644 --- a/drivers/xen/netback/interface.c +++ b/drivers/xen/netback/interface.c @@ -4,377 +4,336 @@ * Network-device interface management. * * Copyright (c) 2004-2005, Keir Fraser + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ #include "common.h" +#include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#endif - -#define NETIF_HASHSZ 1024 -#define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1)) - -static netif_t *netif_hash[NETIF_HASHSZ]; - -netif_t *netif_find_by_handle(domid_t domid, unsigned int handle) -{ - netif_t *netif = netif_hash[NETIF_HASH(domid, handle)]; - while ( (netif != NULL) && - ((netif->domid != domid) || (netif->handle != handle)) ) - netif = netif->hash_next; - return netif; -} - static void __netif_up(netif_t *netif) { - struct net_device *dev = netif->dev; - spin_lock_bh(&dev->xmit_lock); - netif->active = 1; - spin_unlock_bh(&dev->xmit_lock); - (void)request_irq(netif->irq, netif_be_int, 0, dev->name, netif); - netif_schedule_work(netif); + enable_irq(netif->irq); + netif_schedule_work(netif); } static void __netif_down(netif_t *netif) { - struct net_device *dev = netif->dev; - spin_lock_bh(&dev->xmit_lock); - netif->active = 0; - spin_unlock_bh(&dev->xmit_lock); - free_irq(netif->irq, netif); - netif_deschedule_work(netif); + disable_irq(netif->irq); + netif_deschedule_work(netif); } static int net_open(struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - if ( netif->status == CONNECTED ) - __netif_up(netif); - netif_start_queue(dev); - return 0; + netif_t *netif = netdev_priv(dev); + if (netif_carrier_ok(dev)) + __netif_up(netif); + return 0; } static int net_close(struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - netif_stop_queue(dev); - if ( netif->status == CONNECTED ) - __netif_down(netif); - return 0; + netif_t *netif = netdev_priv(dev); + if (netif_carrier_ok(dev)) + __netif_down(netif); + return 0; } -static void __netif_disconnect_complete(void *arg) +static int netbk_change_mtu(struct net_device *dev, int mtu) { - netif_t *netif = (netif_t *)arg; - ctrl_msg_t cmsg; - netif_be_disconnect_t disc; - - /* - * These can't be done in netif_disconnect() because at that point there - * may be outstanding requests in the network stack whose asynchronous - * responses must still be notified to the remote driver. - */ - unbind_evtchn_from_irq(netif->evtchn); - vfree(netif->tx); /* Frees netif->rx as well. */ - - /* Construct the deferred response message. */ - cmsg.type = CMSG_NETIF_BE; - cmsg.subtype = CMSG_NETIF_BE_DISCONNECT; - cmsg.id = netif->disconnect_rspid; - cmsg.length = sizeof(netif_be_disconnect_t); - disc.domid = netif->domid; - disc.netif_handle = netif->handle; - disc.status = NETIF_BE_STATUS_OKAY; - memcpy(cmsg.msg, &disc, sizeof(disc)); - - /* - * Make sure message is constructed /before/ status change, because - * after the status change the 'netif' structure could be deallocated at - * any time. Also make sure we send the response /after/ status change, - * as otherwise a subsequent CONNECT request could spuriously fail if - * another CPU doesn't see the status change yet. - */ - mb(); - if ( netif->status != DISCONNECTING ) - BUG(); - netif->status = DISCONNECTED; - mb(); - - /* Send the successful response. */ - ctrl_if_send_response(&cmsg); + int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN; + + if (mtu > max) + return -EINVAL; + dev->mtu = mtu; + return 0; } -void netif_disconnect_complete(netif_t *netif) +static int netbk_set_sg(struct net_device *dev, u32 data) { - INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif); - schedule_work(&netif->work); + if (data) { + netif_t *netif = netdev_priv(dev); + + if (!(netif->features & NETIF_F_SG)) + return -ENOSYS; + } + + return ethtool_op_set_sg(dev, data); } -void netif_create(netif_be_create_t *create) +static int netbk_set_tso(struct net_device *dev, u32 data) { - int err = 0; - domid_t domid = create->domid; - unsigned int handle = create->netif_handle; - struct net_device *dev; - netif_t **pnetif, *netif; - char name[IFNAMSIZ] = {}; - - snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle); - dev = alloc_netdev(sizeof(netif_t), name, ether_setup); - if ( dev == NULL ) - { - DPRINTK("Could not create netif: out of memory\n"); - create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - netif = netdev_priv(dev); - memset(netif, 0, sizeof(*netif)); - netif->domid = domid; - netif->handle = handle; - netif->status = DISCONNECTED; - atomic_set(&netif->refcnt, 0); - netif->dev = dev; - - netif->credit_bytes = netif->remaining_credit = ~0UL; - netif->credit_usec = 0UL; - init_timer(&netif->credit_timeout); - - pnetif = &netif_hash[NETIF_HASH(domid, handle)]; - while ( *pnetif != NULL ) - { - if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) ) - { - DPRINTK("Could not create netif: already exists\n"); - create->status = NETIF_BE_STATUS_INTERFACE_EXISTS; - free_netdev(dev); - return; - } - pnetif = &(*pnetif)->hash_next; - } - - dev->hard_start_xmit = netif_be_start_xmit; - dev->get_stats = netif_be_get_stats; - dev->open = net_open; - dev->stop = net_close; - - /* Disable queuing. */ - dev->tx_queue_len = 0; - - if ( (create->be_mac[0] == 0) && (create->be_mac[1] == 0) && - (create->be_mac[2] == 0) && (create->be_mac[3] == 0) && - (create->be_mac[4] == 0) && (create->be_mac[5] == 0) ) - { - /* - * Initialise a dummy MAC address. We choose the numerically largest - * non-broadcast address to prevent the address getting stolen by an - * Ethernet bridge for STP purposes. (FE:FF:FF:FF:FF:FF) - */ - memset(dev->dev_addr, 0xFF, ETH_ALEN); - dev->dev_addr[0] &= ~0x01; - } - else - { - memcpy(dev->dev_addr, create->be_mac, ETH_ALEN); - } - - memcpy(netif->fe_dev_addr, create->mac, ETH_ALEN); - - rtnl_lock(); - err = register_netdevice(dev); - rtnl_unlock(); - - if ( err != 0 ) - { - DPRINTK("Could not register new net device %s: err=%d\n", - dev->name, err); - create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - free_netdev(dev); - return; - } - - netif->hash_next = *pnetif; - *pnetif = netif; - - DPRINTK("Successfully created netif\n"); - create->status = NETIF_BE_STATUS_OKAY; + if (data) { + netif_t *netif = netdev_priv(dev); + + if (!(netif->features & NETIF_F_TSO)) + return -ENOSYS; + } + + return ethtool_op_set_tso(dev, data); } -void netif_destroy(netif_be_destroy_t *destroy) +static struct ethtool_ops network_ethtool_ops = { - domid_t domid = destroy->domid; - unsigned int handle = destroy->netif_handle; - netif_t **pnetif, *netif; - - pnetif = &netif_hash[NETIF_HASH(domid, handle)]; - while ( (netif = *pnetif) != NULL ) - { - if ( (netif->domid == domid) && (netif->handle == handle) ) - { - if ( netif->status != DISCONNECTED ) - goto still_connected; - goto destroy; - } - pnetif = &netif->hash_next; - } - - destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - - still_connected: - destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED; - return; - - destroy: - *pnetif = netif->hash_next; - unregister_netdev(netif->dev); - free_netdev(netif->dev); - destroy->status = NETIF_BE_STATUS_OKAY; + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = netbk_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = netbk_set_tso, + .get_link = ethtool_op_get_link, +}; + +netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]) +{ + int err = 0, i; + struct net_device *dev; + netif_t *netif; + char name[IFNAMSIZ] = {}; + + snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle); + dev = alloc_netdev(sizeof(netif_t), name, ether_setup); + if (dev == NULL) { + DPRINTK("Could not create netif: out of memory\n"); + return ERR_PTR(-ENOMEM); + } + + netif_carrier_off(dev); + + netif = netdev_priv(dev); + memset(netif, 0, sizeof(*netif)); + netif->domid = domid; + netif->handle = handle; + atomic_set(&netif->refcnt, 1); + init_waitqueue_head(&netif->waiting_to_free); + netif->dev = dev; + + netif->credit_bytes = netif->remaining_credit = ~0UL; + netif->credit_usec = 0UL; + init_timer(&netif->credit_timeout); + + dev->hard_start_xmit = netif_be_start_xmit; + dev->get_stats = netif_be_get_stats; + dev->open = net_open; + dev->stop = net_close; + dev->change_mtu = netbk_change_mtu; + dev->features = NETIF_F_IP_CSUM; + + SET_ETHTOOL_OPS(dev, &network_ethtool_ops); + + /* + * Reduce default TX queuelen so that each guest interface only + * allows it to eat around 6.4MB of host memory. + */ + dev->tx_queue_len = 100; + + for (i = 0; i < ETH_ALEN; i++) + if (be_mac[i] != 0) + break; + if (i == ETH_ALEN) { + /* + * Initialise a dummy MAC address. We choose the numerically + * largest non-broadcast address to prevent the address getting + * stolen by an Ethernet bridge for STP purposes. + * (FE:FF:FF:FF:FF:FF) + */ + memset(dev->dev_addr, 0xFF, ETH_ALEN); + dev->dev_addr[0] &= ~0x01; + } else + memcpy(dev->dev_addr, be_mac, ETH_ALEN); + + rtnl_lock(); + err = register_netdevice(dev); + rtnl_unlock(); + if (err) { + DPRINTK("Could not register new net device %s: err=%d\n", + dev->name, err); + free_netdev(dev); + return ERR_PTR(err); + } + + DPRINTK("Successfully created netif\n"); + return netif; } -void netif_creditlimit(netif_be_creditlimit_t *creditlimit) +static int map_frontend_pages( + netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref) { - domid_t domid = creditlimit->domid; - unsigned int handle = creditlimit->netif_handle; - netif_t *netif; - - netif = netif_find_by_handle(domid, handle); - if ( unlikely(netif == NULL) ) - { - DPRINTK("netif_creditlimit attempted for non-existent netif" - " (%u,%u)\n", creditlimit->domid, creditlimit->netif_handle); - creditlimit->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - /* Set the credit limit (reset remaining credit to new limit). */ - netif->credit_bytes = netif->remaining_credit = creditlimit->credit_bytes; - netif->credit_usec = creditlimit->period_usec; - - if ( netif->status == CONNECTED ) - { - /* - * Schedule work so that any packets waiting under previous credit - * limit are dealt with (acts like a replenishment point). - */ - netif->credit_timeout.expires = jiffies; - netif_schedule_work(netif); - } + struct gnttab_map_grant_ref op; + int ret; + + gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr, + GNTMAP_host_map, tx_ring_ref, netif->domid); - creditlimit->status = NETIF_BE_STATUS_OKAY; + lock_vm_area(netif->tx_comms_area); + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); + unlock_vm_area(netif->tx_comms_area); + BUG_ON(ret); + + if (op.status) { + DPRINTK(" Gnttab failure mapping tx_ring_ref!\n"); + return op.status; + } + + netif->tx_shmem_ref = tx_ring_ref; + netif->tx_shmem_handle = op.handle; + + gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr, + GNTMAP_host_map, rx_ring_ref, netif->domid); + + lock_vm_area(netif->rx_comms_area); + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); + unlock_vm_area(netif->rx_comms_area); + BUG_ON(ret); + + if (op.status) { + DPRINTK(" Gnttab failure mapping rx_ring_ref!\n"); + return op.status; + } + + netif->rx_shmem_ref = rx_ring_ref; + netif->rx_shmem_handle = op.handle; + + return 0; } -void netif_connect(netif_be_connect_t *connect) +static void unmap_frontend_pages(netif_t *netif) { - domid_t domid = connect->domid; - unsigned int handle = connect->netif_handle; - unsigned int evtchn = connect->evtchn; - unsigned long tx_shmem_frame = connect->tx_shmem_frame; - unsigned long rx_shmem_frame = connect->rx_shmem_frame; - struct vm_struct *vma; - pgprot_t prot; - int error; - netif_t *netif; - - netif = netif_find_by_handle(domid, handle); - if ( unlikely(netif == NULL) ) - { - DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n", - connect->domid, connect->netif_handle); - connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - if ( netif->status != DISCONNECTED ) - { - connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED; - return; - } - - if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL ) - { - connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED); - error = direct_remap_area_pages(&init_mm, - VMALLOC_VMADDR(vma->addr), - tx_shmem_frame<addr) + PAGE_SIZE, - rx_shmem_frame<status = NETIF_BE_STATUS_OUT_OF_MEMORY; - else if ( error == -EFAULT ) - connect->status = NETIF_BE_STATUS_MAPPING_ERROR; - else - connect->status = NETIF_BE_STATUS_ERROR; - vfree(vma->addr); - return; - } - - netif->evtchn = evtchn; - netif->irq = bind_evtchn_to_irq(evtchn); - netif->tx_shmem_frame = tx_shmem_frame; - netif->rx_shmem_frame = rx_shmem_frame; - netif->tx = - (netif_tx_interface_t *)vma->addr; - netif->rx = - (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE); - netif->tx->resp_prod = netif->rx->resp_prod = 0; - netif_get(netif); - wmb(); /* Other CPUs see new state before interface is started. */ - - rtnl_lock(); - netif->status = CONNECTED; - wmb(); - if ( netif_running(netif->dev) ) - __netif_up(netif); - rtnl_unlock(); - - connect->status = NETIF_BE_STATUS_OKAY; + struct gnttab_unmap_grant_ref op; + int ret; + + gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr, + GNTMAP_host_map, netif->tx_shmem_handle); + + lock_vm_area(netif->tx_comms_area); + ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); + unlock_vm_area(netif->tx_comms_area); + BUG_ON(ret); + + gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr, + GNTMAP_host_map, netif->rx_shmem_handle); + + lock_vm_area(netif->rx_comms_area); + ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); + unlock_vm_area(netif->rx_comms_area); + BUG_ON(ret); +} + +int netif_map(netif_t *netif, unsigned long tx_ring_ref, + unsigned long rx_ring_ref, unsigned int evtchn) +{ + int err = -ENOMEM; + netif_tx_sring_t *txs; + netif_rx_sring_t *rxs; + struct evtchn_bind_interdomain bind_interdomain; + + /* Already connected through? */ + if (netif->irq) + return 0; + + netif->tx_comms_area = alloc_vm_area(PAGE_SIZE); + if (netif->tx_comms_area == NULL) + return -ENOMEM; + netif->rx_comms_area = alloc_vm_area(PAGE_SIZE); + if (netif->rx_comms_area == NULL) + goto err_rx; + + err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref); + if (err) + goto err_map; + + bind_interdomain.remote_dom = netif->domid; + bind_interdomain.remote_port = evtchn; + + err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, + &bind_interdomain); + if (err) + goto err_hypervisor; + + netif->evtchn = bind_interdomain.local_port; + + netif->irq = bind_evtchn_to_irqhandler( + netif->evtchn, netif_be_int, 0, netif->dev->name, netif); + disable_irq(netif->irq); + + txs = (netif_tx_sring_t *)netif->tx_comms_area->addr; + BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE); + + rxs = (netif_rx_sring_t *) + ((char *)netif->rx_comms_area->addr); + BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE); + + netif->rx_req_cons_peek = 0; + + netif_get(netif); + + rtnl_lock(); + netif_carrier_on(netif->dev); + if (netif_running(netif->dev)) + __netif_up(netif); + rtnl_unlock(); + + return 0; +err_hypervisor: + unmap_frontend_pages(netif); +err_map: + free_vm_area(netif->rx_comms_area); +err_rx: + free_vm_area(netif->tx_comms_area); + return err; } -int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id) +static void netif_free(netif_t *netif) { - domid_t domid = disconnect->domid; - unsigned int handle = disconnect->netif_handle; - netif_t *netif; - - netif = netif_find_by_handle(domid, handle); - if ( unlikely(netif == NULL) ) - { - DPRINTK("netif_disconnect attempted for non-existent netif" - " (%u,%u)\n", disconnect->domid, disconnect->netif_handle); - disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND; - return 1; /* Caller will send response error message. */ - } - - if ( netif->status == CONNECTED ) - { - rtnl_lock(); - netif->status = DISCONNECTING; - netif->disconnect_rspid = rsp_id; - wmb(); - if ( netif_running(netif->dev) ) - __netif_down(netif); - rtnl_unlock(); - netif_put(netif); - return 0; /* Caller should not send response message. */ - } - - disconnect->status = NETIF_BE_STATUS_OKAY; - return 1; + atomic_dec(&netif->refcnt); + wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0); + + if (netif->irq) + unbind_from_irqhandler(netif->irq, netif); + + unregister_netdev(netif->dev); + + if (netif->tx.sring) { + unmap_frontend_pages(netif); + free_vm_area(netif->tx_comms_area); + free_vm_area(netif->rx_comms_area); + } + + free_netdev(netif->dev); } -void netif_interface_init(void) +void netif_disconnect(netif_t *netif) { - memset(netif_hash, 0, sizeof(netif_hash)); + if (netif_carrier_ok(netif->dev)) { + rtnl_lock(); + netif_carrier_off(netif->dev); + if (netif_running(netif->dev)) + __netif_down(netif); + rtnl_unlock(); + netif_put(netif); + } + netif_free(netif); } diff --git a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c index d08c296a0..0316f3b05 100644 --- a/drivers/xen/netback/netback.c +++ b/drivers/xen/netback/netback.c @@ -8,26 +8,54 @@ * drivers/xen/netfront/netfront.c * * Copyright (c) 2002-2005, K A Fraser + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ #include "common.h" -#include -#include +#include +#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#include -#endif +/*#define NETBE_DEBUG_INTERRUPT*/ + +struct netbk_rx_meta { + skb_frag_t frag; + int id; +}; static void netif_idx_release(u16 pending_idx); static void netif_page_release(struct page *page); static void make_tx_response(netif_t *netif, - u16 id, - s8 st); -static int make_rx_response(netif_t *netif, - u16 id, - s8 st, - memory_t addr, - u16 size); + netif_tx_request_t *txp, + s8 st); +static netif_rx_response_t *make_rx_response(netif_t *netif, + u16 id, + s8 st, + u16 offset, + u16 size, + u16 flags); static void net_tx_action(unsigned long unused); static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0); @@ -37,24 +65,22 @@ static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0); static struct timer_list net_timer; -static struct sk_buff_head rx_queue; -static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1]; -static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; -static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE]; -static unsigned char rx_notify[NR_EVENT_CHANNELS]; +#define MAX_PENDING_REQS 256 -/* Don't currently gate addition of an interface to the tx scheduling list. */ -#define tx_work_exists(_if) (1) +static struct sk_buff_head rx_queue; +static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1]; +static mmu_update_t rx_mmu[NET_RX_RING_SIZE]; +static gnttab_transfer_t grant_rx_op[NET_RX_RING_SIZE]; +static unsigned char rx_notify[NR_IRQS]; -#define MAX_PENDING_REQS 256 static unsigned long mmap_vstart; #define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE)) #define PKT_PROT_LEN 64 static struct { - netif_tx_request_t req; - netif_t *netif; + netif_tx_request_t req; + netif_t *netif; } pending_tx_info[MAX_PENDING_REQS]; static u16 pending_ring[MAX_PENDING_REQS]; typedef unsigned int PEND_RING_IDX; @@ -67,7 +93,10 @@ static u16 dealloc_ring[MAX_PENDING_REQS]; static PEND_RING_IDX dealloc_prod, dealloc_cons; static struct sk_buff_head tx_queue; -static multicall_entry_t tx_mcl[MAX_PENDING_REQS]; + +static grant_handle_t grant_tx_handle[MAX_PENDING_REQS]; +static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS]; +static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS]; static struct list_head net_schedule_list; static spinlock_t net_schedule_list_lock; @@ -75,39 +104,36 @@ static spinlock_t net_schedule_list_lock; #define MAX_MFN_ALLOC 64 static unsigned long mfn_list[MAX_MFN_ALLOC]; static unsigned int alloc_index = 0; -static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED; -static unsigned long alloc_mfn(void) +static inline unsigned long alloc_mfn(void) { - unsigned long mfn = 0, flags; - spin_lock_irqsave(&mfn_lock, flags); - if ( unlikely(alloc_index == 0) ) - alloc_index = HYPERVISOR_dom_mem_op( - MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0); - if ( alloc_index != 0 ) - mfn = mfn_list[--alloc_index]; - spin_unlock_irqrestore(&mfn_lock, flags); - return mfn; + return mfn_list[--alloc_index]; } -static void free_mfn(unsigned long mfn) +static int check_mfn(int nr) { - unsigned long flags; - spin_lock_irqsave(&mfn_lock, flags); - if ( alloc_index != MAX_MFN_ALLOC ) - mfn_list[alloc_index++] = mfn; - else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, - &mfn, 1, 0) != 1 ) - BUG(); - spin_unlock_irqrestore(&mfn_lock, flags); + struct xen_memory_reservation reservation = { + .extent_order = 0, + .domid = DOMID_SELF + }; + + if (likely(alloc_index >= nr)) + return 0; + + set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index); + reservation.nr_extents = MAX_MFN_ALLOC - alloc_index; + alloc_index += HYPERVISOR_memory_op(XENMEM_increase_reservation, + &reservation); + + return alloc_index >= nr ? 0 : -ENOMEM; } static inline void maybe_schedule_tx_action(void) { - smp_mb(); - if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) && - !list_empty(&net_schedule_list) ) - tasklet_schedule(&net_tx_tasklet); + smp_mb(); + if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) && + !list_empty(&net_schedule_list)) + tasklet_schedule(&net_tx_tasklet); } /* @@ -116,69 +142,166 @@ static inline void maybe_schedule_tx_action(void) */ static inline int is_xen_skb(struct sk_buff *skb) { - extern kmem_cache_t *skbuff_cachep; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next; -#else - kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->list.next; -#endif - return (cp == skbuff_cachep); + extern kmem_cache_t *skbuff_cachep; + kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next; + return (cp == skbuff_cachep); +} + +static struct sk_buff *netbk_copy_skb(struct sk_buff *skb) +{ + struct skb_shared_info *ninfo; + struct sk_buff *nskb; + unsigned long offset; + int ret; + int len; + int headlen; + + nskb = alloc_skb(SKB_MAX_HEAD(0), GFP_ATOMIC); + if (unlikely(!nskb)) + goto err; + + skb_reserve(nskb, 16); + headlen = nskb->end - nskb->data; + if (headlen > skb_headlen(skb)) + headlen = skb_headlen(skb); + ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen); + BUG_ON(ret); + + ninfo = skb_shinfo(nskb); + ninfo->gso_size = skb_shinfo(skb)->gso_size; + ninfo->gso_type = skb_shinfo(skb)->gso_type; + + offset = headlen; + len = skb->len - headlen; + + nskb->len = skb->len; + nskb->data_len = len; + nskb->truesize += len; + + while (len) { + struct page *page; + int copy; + int zero; + + if (unlikely(ninfo->nr_frags >= MAX_SKB_FRAGS)) { + dump_stack(); + goto err_free; + } + + copy = len >= PAGE_SIZE ? PAGE_SIZE : len; + zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO; + + page = alloc_page(GFP_ATOMIC | zero); + if (unlikely(!page)) + goto err_free; + + ret = skb_copy_bits(skb, offset, page_address(page), copy); + BUG_ON(ret); + + ninfo->frags[ninfo->nr_frags].page = page; + ninfo->frags[ninfo->nr_frags].page_offset = 0; + ninfo->frags[ninfo->nr_frags].size = copy; + ninfo->nr_frags++; + + offset += copy; + len -= copy; + } + + offset = nskb->data - skb->data; + + nskb->h.raw = skb->h.raw + offset; + nskb->nh.raw = skb->nh.raw + offset; + nskb->mac.raw = skb->mac.raw + offset; + + return nskb; + + err_free: + kfree_skb(nskb); + err: + return NULL; +} + +static inline int netbk_max_required_rx_slots(netif_t *netif) +{ + if (netif->features & (NETIF_F_SG|NETIF_F_TSO)) + return MAX_SKB_FRAGS + 2; /* header + extra_info + frags */ + return 1; /* all in one */ +} + +static inline int netbk_queue_full(netif_t *netif) +{ + RING_IDX peek = netif->rx_req_cons_peek; + RING_IDX needed = netbk_max_required_rx_slots(netif); + + return ((netif->rx.sring->req_prod - peek) < needed) || + ((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed); } int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - - ASSERT(skb->dev == dev); - - /* Drop the packet if the target domain has no receive buffers. */ - if ( !netif->active || - (netif->rx_req_cons == netif->rx->req_prod) || - ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) ) - goto drop; - - /* - * We do not copy the packet unless: - * 1. The data is shared; or - * 2. The data is not allocated from our special cache. - * NB. We also couldn't cope with fragmented packets, but we won't get - * any because we not advertise the NETIF_F_SG feature. - */ - if ( skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb) ) - { - int hlen = skb->data - skb->head; - struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len); - if ( unlikely(nskb == NULL) ) - goto drop; - skb_reserve(nskb, hlen); - __skb_put(nskb, skb->len); - (void)skb_copy_bits(skb, -hlen, nskb->data - hlen, skb->len + hlen); - nskb->dev = skb->dev; - dev_kfree_skb(skb); - skb = nskb; - } - - netif->rx_req_cons++; - netif_get(netif); - - skb_queue_tail(&rx_queue, skb); - tasklet_schedule(&net_rx_tasklet); - - return 0; + netif_t *netif = netdev_priv(dev); + + BUG_ON(skb->dev != dev); + + /* Drop the packet if the target domain has no receive buffers. */ + if (unlikely(!netif_running(dev) || !netif_carrier_ok(dev))) + goto drop; + + if (unlikely(netbk_queue_full(netif))) { + /* Not a BUG_ON() -- misbehaving netfront can trigger this. */ + if (netbk_can_queue(dev)) + DPRINTK("Queue full but not stopped!\n"); + goto drop; + } + + /* + * We do not copy the packet unless: + * 1. The data is shared; or + * 2. The data is not allocated from our special cache. + * 3. The data is fragmented. + */ + if (skb_cloned(skb) || skb_is_nonlinear(skb) || !is_xen_skb(skb)) { + struct sk_buff *nskb = netbk_copy_skb(skb); + if ( unlikely(nskb == NULL) ) + goto drop; + /* Copy only the header fields we use in this driver. */ + nskb->dev = skb->dev; + nskb->ip_summed = skb->ip_summed; + nskb->proto_data_valid = skb->proto_data_valid; + dev_kfree_skb(skb); + skb = nskb; + } + + netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 + + !!skb_shinfo(skb)->gso_size; + netif_get(netif); + + if (netbk_can_queue(dev) && netbk_queue_full(netif)) { + netif->rx.sring->req_event = netif->rx_req_cons_peek + + netbk_max_required_rx_slots(netif); + mb(); /* request notification /then/ check & stop the queue */ + if (netbk_queue_full(netif)) + netif_stop_queue(dev); + } + + skb_queue_tail(&rx_queue, skb); + tasklet_schedule(&net_rx_tasklet); + + return 0; drop: - netif->stats.tx_dropped++; - dev_kfree_skb(skb); - return 0; + netif->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; } #if 0 static void xen_network_done_notify(void) { - static struct net_device *eth0_dev = NULL; - if ( unlikely(eth0_dev == NULL) ) - eth0_dev = __dev_get_by_name("eth0"); - netif_rx_schedule(eth0_dev); + static struct net_device *eth0_dev = NULL; + if (unlikely(eth0_dev == NULL)) + eth0_dev = __dev_get_by_name("eth0"); + netif_rx_schedule(eth0_dev); } /* * Add following to poll() function in NAPI driver (Tigon3 is example): @@ -187,633 +310,1036 @@ static void xen_network_done_notify(void) */ int xen_network_done(void) { - return skb_queue_empty(&rx_queue); + return skb_queue_empty(&rx_queue); } #endif +static u16 netbk_gop_frag(netif_t *netif, struct page *page, int count, int i) +{ + multicall_entry_t *mcl = rx_mcl + count; + mmu_update_t *mmu = rx_mmu + count; + gnttab_transfer_t *gop = grant_rx_op + count; + netif_rx_request_t *req; + unsigned long old_mfn, new_mfn; + + old_mfn = virt_to_mfn(page_address(page)); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + new_mfn = alloc_mfn(); + + /* + * Set the new P2M table entry before reassigning + * the old data page. Heed the comment in + * pgtable-2level.h:pte_page(). :-) + */ + set_phys_to_machine(page_to_pfn(page), new_mfn); + + MULTI_update_va_mapping(mcl, (unsigned long)page_address(page), + pfn_pte_ma(new_mfn, PAGE_KERNEL), 0); + + mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE; + mmu->val = page_to_pfn(page); + } + + req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i); + gop->mfn = old_mfn; + gop->domid = netif->domid; + gop->ref = req->gref; + return req->id; +} + +static void netbk_gop_skb(struct sk_buff *skb, struct netbk_rx_meta *meta, + int count) +{ + netif_t *netif = netdev_priv(skb->dev); + int nr_frags = skb_shinfo(skb)->nr_frags; + int i; + int extra; + + meta[count].frag.page_offset = skb_shinfo(skb)->gso_type; + meta[count].frag.size = skb_shinfo(skb)->gso_size; + extra = !!meta[count].frag.size + 1; + + for (i = 0; i < nr_frags; i++) { + meta[++count].frag = skb_shinfo(skb)->frags[i]; + meta[count].id = netbk_gop_frag(netif, meta[count].frag.page, + count, i + extra); + } + + /* + * This must occur at the end to ensure that we don't trash + * skb_shinfo until we're done. + */ + meta[count - nr_frags].id = netbk_gop_frag(netif, + virt_to_page(skb->data), + count - nr_frags, 0); + netif->rx.req_cons += nr_frags + extra; +} + +static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta) +{ + int i; + + for (i = 0; i < nr_frags; i++) + put_page(meta[i].frag.page); +} + +static int netbk_check_gop(int nr_frags, domid_t domid, int count) +{ + multicall_entry_t *mcl = rx_mcl + count; + gnttab_transfer_t *gop = grant_rx_op + count; + int status = NETIF_RSP_OKAY; + int i; + + for (i = 0; i <= nr_frags; i++) { + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* The update_va_mapping() must not fail. */ + BUG_ON(mcl->result != 0); + mcl++; + } + + /* Check the reassignment error code. */ + if (gop->status != 0) { + DPRINTK("Bad status %d from grant transfer to DOM%u\n", + gop->status, domid); + /* + * Page no longer belongs to us unless GNTST_bad_page, + * but that should be a fatal error anyway. + */ + BUG_ON(gop->status == GNTST_bad_page); + status = NETIF_RSP_ERROR; + } + gop++; + } + + return status; +} + +static void netbk_add_frag_responses(netif_t *netif, int status, + struct netbk_rx_meta *meta, int nr_frags) +{ + int i; + + for (i = 0; i < nr_frags; i++) { + int id = meta[i].id; + int flags = (i == nr_frags - 1) ? 0 : NETRXF_more_data; + + make_rx_response(netif, id, status, meta[i].frag.page_offset, + meta[i].frag.size, flags); + } +} + static void net_rx_action(unsigned long unused) { - netif_t *netif; - s8 status; - u16 size, id, evtchn; - multicall_entry_t *mcl; - mmu_update_t *mmu; - struct mmuext_op *mmuext; - unsigned long vdata, mdata, new_mfn; - struct sk_buff_head rxq; - struct sk_buff *skb; - u16 notify_list[NETIF_RX_RING_SIZE]; - int notify_nr = 0; - - skb_queue_head_init(&rxq); - - mcl = rx_mcl; - mmu = rx_mmu; - mmuext = rx_mmuext; - while ( (skb = skb_dequeue(&rx_queue)) != NULL ) - { - netif = netdev_priv(skb->dev); - vdata = (unsigned long)skb->data; - mdata = virt_to_machine(vdata); - - /* Memory squeeze? Back off for an arbitrary while. */ - if ( (new_mfn = alloc_mfn()) == 0 ) - { - if ( net_ratelimit() ) - printk(KERN_WARNING "Memory squeeze in netback driver.\n"); - mod_timer(&net_timer, jiffies + HZ); - skb_queue_head(&rx_queue, skb); - break; - } - - /* - * Set the new P2M table entry before reassigning the old data page. - * Heed the comment in pgtable-2level.h:pte_page(). :-) - */ - phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn; - - mcl->op = __HYPERVISOR_update_va_mapping; - mcl->args[0] = vdata; - mcl->args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL; - mcl->args[2] = 0; - mcl++; - - mcl->op = __HYPERVISOR_mmuext_op; - mcl->args[0] = (unsigned long)mmuext; - mcl->args[1] = 1; - mcl->args[2] = 0; - mcl->args[3] = netif->domid; - mcl++; - - mmuext->cmd = MMUEXT_REASSIGN_PAGE; - mmuext->mfn = mdata >> PAGE_SHIFT; - mmuext++; - - mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; - mmu->val = __pa(vdata) >> PAGE_SHIFT; - mmu++; - - __skb_queue_tail(&rxq, skb); - - /* Filled the batch queue? */ - if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) ) - break; - } - - if ( mcl == rx_mcl ) - return; - - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; - mcl->args[2] = 0; - mcl->args[3] = DOMID_SELF; - mcl++; - - mcl[-3].args[2] = UVMF_TLB_FLUSH|UVMF_ALL; - if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) ) - BUG(); - - mcl = rx_mcl; - mmuext = rx_mmuext; - while ( (skb = __skb_dequeue(&rxq)) != NULL ) - { - netif = netdev_priv(skb->dev); - size = skb->tail - skb->data; - - /* Rederive the machine addresses. */ - new_mfn = mcl[0].args[1] >> PAGE_SHIFT; - mdata = ((mmuext[0].mfn << PAGE_SHIFT) | - ((unsigned long)skb->data & ~PAGE_MASK)); - - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; - - netif->stats.tx_bytes += size; - netif->stats.tx_packets++; - - /* The update_va_mapping() must not fail. */ - if ( unlikely(mcl[0].args[5] != 0) ) - BUG(); - - /* Check the reassignment error code. */ - status = NETIF_RSP_OKAY; - if ( unlikely(mcl[1].args[5] != 0) ) - { - DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid); - free_mfn(mdata >> PAGE_SHIFT); - status = NETIF_RSP_ERROR; - } - - evtchn = netif->evtchn; - id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; - if ( make_rx_response(netif, id, status, mdata, size) && - (rx_notify[evtchn] == 0) ) - { - rx_notify[evtchn] = 1; - notify_list[notify_nr++] = evtchn; - } - - netif_put(netif); - dev_kfree_skb(skb); - - mcl += 2; - mmuext += 1; - } - - while ( notify_nr != 0 ) - { - evtchn = notify_list[--notify_nr]; - rx_notify[evtchn] = 0; - notify_via_evtchn(evtchn); - } - - /* More work to do? */ - if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) ) - tasklet_schedule(&net_rx_tasklet); + netif_t *netif = NULL; + s8 status; + u16 id, irq, flags; + netif_rx_response_t *resp; + struct netif_extra_info *extra; + multicall_entry_t *mcl; + struct sk_buff_head rxq; + struct sk_buff *skb; + int notify_nr = 0; + int ret; + int nr_frags; + int count; + + /* + * Putting hundreds of bytes on the stack is considered rude. + * Static works because a tasklet can only be on one CPU at any time. + */ + static u16 notify_list[NET_RX_RING_SIZE]; + static struct netbk_rx_meta meta[NET_RX_RING_SIZE]; + + skb_queue_head_init(&rxq); + + count = 0; + + while ((skb = skb_dequeue(&rx_queue)) != NULL) { + nr_frags = skb_shinfo(skb)->nr_frags; + *(int *)skb->cb = nr_frags; + + if (!xen_feature(XENFEAT_auto_translated_physmap) && + check_mfn(nr_frags + 1)) { + /* Memory squeeze? Back off for an arbitrary while. */ + if ( net_ratelimit() ) + WPRINTK("Memory squeeze in netback " + "driver.\n"); + mod_timer(&net_timer, jiffies + HZ); + skb_queue_head(&rx_queue, skb); + break; + } + + netbk_gop_skb(skb, meta, count); + + count += nr_frags + 1; + + __skb_queue_tail(&rxq, skb); + + /* Filled the batch queue? */ + if (count + MAX_SKB_FRAGS >= NET_RX_RING_SIZE) + break; + } + + if (!count) + return; + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + mcl = rx_mcl + count; + + mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + + mcl->op = __HYPERVISOR_mmu_update; + mcl->args[0] = (unsigned long)rx_mmu; + mcl->args[1] = count; + mcl->args[2] = 0; + mcl->args[3] = DOMID_SELF; + + ret = HYPERVISOR_multicall(rx_mcl, count + 1); + BUG_ON(ret != 0); + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, count); + BUG_ON(ret != 0); + + count = 0; + while ((skb = __skb_dequeue(&rxq)) != NULL) { + nr_frags = *(int *)skb->cb; + + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->frag_list = NULL; + + netif = netdev_priv(skb->dev); + netif->stats.tx_bytes += skb->len; + netif->stats.tx_packets++; + + netbk_free_pages(nr_frags, meta + count + 1); + status = netbk_check_gop(nr_frags, netif->domid, count); + + id = meta[count].id; + flags = nr_frags ? NETRXF_more_data : 0; + + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ + flags |= NETRXF_csum_blank | NETRXF_data_validated; + else if (skb->proto_data_valid) /* remote but checksummed? */ + flags |= NETRXF_data_validated; + + resp = make_rx_response(netif, id, status, + offset_in_page(skb->data), + skb_headlen(skb), flags); + + extra = NULL; + + if (meta[count].frag.size) { + struct netif_extra_info *gso = + (struct netif_extra_info *) + RING_GET_RESPONSE(&netif->rx, + netif->rx.rsp_prod_pvt++); + + if (extra) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + resp->flags |= NETRXF_extra_info; + + gso->u.gso.size = meta[count].frag.size; + gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + gso->u.gso.pad = 0; + gso->u.gso.features = 0; + + gso->type = XEN_NETIF_EXTRA_TYPE_GSO; + gso->flags = 0; + extra = gso; + } + + netbk_add_frag_responses(netif, status, meta + count + 1, + nr_frags); + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret); + irq = netif->irq; + if (ret && !rx_notify[irq]) { + rx_notify[irq] = 1; + notify_list[notify_nr++] = irq; + } + + if (netif_queue_stopped(netif->dev) && + !netbk_queue_full(netif)) + netif_wake_queue(netif->dev); + + netif_put(netif); + dev_kfree_skb(skb); + count += nr_frags + 1; + } + + while (notify_nr != 0) { + irq = notify_list[--notify_nr]; + rx_notify[irq] = 0; + notify_remote_via_irq(irq); + } + + /* More work to do? */ + if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer)) + tasklet_schedule(&net_rx_tasklet); #if 0 - else - xen_network_done_notify(); + else + xen_network_done_notify(); #endif } static void net_alarm(unsigned long unused) { - tasklet_schedule(&net_rx_tasklet); + tasklet_schedule(&net_rx_tasklet); } struct net_device_stats *netif_be_get_stats(struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - return &netif->stats; + netif_t *netif = netdev_priv(dev); + return &netif->stats; } static int __on_net_schedule_list(netif_t *netif) { - return netif->list.next != NULL; + return netif->list.next != NULL; } static void remove_from_net_schedule_list(netif_t *netif) { - spin_lock_irq(&net_schedule_list_lock); - if ( likely(__on_net_schedule_list(netif)) ) - { - list_del(&netif->list); - netif->list.next = NULL; - netif_put(netif); - } - spin_unlock_irq(&net_schedule_list_lock); + spin_lock_irq(&net_schedule_list_lock); + if (likely(__on_net_schedule_list(netif))) { + list_del(&netif->list); + netif->list.next = NULL; + netif_put(netif); + } + spin_unlock_irq(&net_schedule_list_lock); } static void add_to_net_schedule_list_tail(netif_t *netif) { - if ( __on_net_schedule_list(netif) ) - return; - - spin_lock_irq(&net_schedule_list_lock); - if ( !__on_net_schedule_list(netif) && netif->active ) - { - list_add_tail(&netif->list, &net_schedule_list); - netif_get(netif); - } - spin_unlock_irq(&net_schedule_list_lock); + if (__on_net_schedule_list(netif)) + return; + + spin_lock_irq(&net_schedule_list_lock); + if (!__on_net_schedule_list(netif) && + likely(netif_running(netif->dev) && + netif_carrier_ok(netif->dev))) { + list_add_tail(&netif->list, &net_schedule_list); + netif_get(netif); + } + spin_unlock_irq(&net_schedule_list_lock); } +/* + * Note on CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER: + * If this driver is pipelining transmit requests then we can be very + * aggressive in avoiding new-packet notifications -- frontend only needs to + * send a notification if there are no outstanding unreceived responses. + * If we may be buffer transmit buffers for any reason then we must be rather + * more conservative and treat this as the final check for pending work. + */ void netif_schedule_work(netif_t *netif) { - if ( (netif->tx_req_cons != netif->tx->req_prod) && - ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) ) - { - add_to_net_schedule_list_tail(netif); - maybe_schedule_tx_action(); - } + int more_to_do; + +#ifdef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER + more_to_do = RING_HAS_UNCONSUMED_REQUESTS(&netif->tx); +#else + RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, more_to_do); +#endif + + if (more_to_do) { + add_to_net_schedule_list_tail(netif); + maybe_schedule_tx_action(); + } } void netif_deschedule_work(netif_t *netif) { - remove_from_net_schedule_list(netif); + remove_from_net_schedule_list(netif); } static void tx_credit_callback(unsigned long data) { - netif_t *netif = (netif_t *)data; - netif->remaining_credit = netif->credit_bytes; - netif_schedule_work(netif); + netif_t *netif = (netif_t *)data; + netif->remaining_credit = netif->credit_bytes; + netif_schedule_work(netif); } -static void net_tx_action(unsigned long unused) +inline static void net_tx_action_dealloc(void) { - struct list_head *ent; - struct sk_buff *skb; - netif_t *netif; - netif_tx_request_t txreq; - u16 pending_idx; - NETIF_RING_IDX i; - multicall_entry_t *mcl; - PEND_RING_IDX dc, dp; - unsigned int data_len; - - if ( (dc = dealloc_cons) == (dp = dealloc_prod) ) - goto skip_dealloc; - - mcl = tx_mcl; - while ( dc != dp ) - { - pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; - mcl[0].op = __HYPERVISOR_update_va_mapping; - mcl[0].args[0] = MMAP_VADDR(pending_idx); - mcl[0].args[1] = 0; - mcl[0].args[2] = 0; - mcl++; - } - - mcl[-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL; - if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) ) - BUG(); - - mcl = tx_mcl; - while ( dealloc_cons != dp ) - { - /* The update_va_mapping() must not fail. */ - if ( unlikely(mcl[0].args[5] != 0) ) - BUG(); - - pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; - - netif = pending_tx_info[pending_idx].netif; - - make_tx_response(netif, pending_tx_info[pending_idx].req.id, - NETIF_RSP_OKAY); - - pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; - - /* - * Scheduling checks must happen after the above response is posted. - * This avoids a possible race with a guest OS on another CPU if that - * guest is testing against 'resp_prod' when deciding whether to notify - * us when it queues additional packets. - */ - mb(); - if ( (netif->tx_req_cons != netif->tx->req_prod) && - ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) ) - add_to_net_schedule_list_tail(netif); - - netif_put(netif); - - mcl++; - } - - skip_dealloc: - mcl = tx_mcl; - while ( (NR_PENDING_REQS < MAX_PENDING_REQS) && - !list_empty(&net_schedule_list) ) - { - /* Get a netif from the list with work to do. */ - ent = net_schedule_list.next; - netif = list_entry(ent, netif_t, list); - netif_get(netif); - remove_from_net_schedule_list(netif); - - /* Work to do? */ - i = netif->tx_req_cons; - if ( (i == netif->tx->req_prod) || - ((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE) ) - { - netif_put(netif); - continue; - } - - rmb(); /* Ensure that we see the request before we copy it. */ - memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, - sizeof(txreq)); - - /* Credit-based scheduling. */ - if ( txreq.size > netif->remaining_credit ) - { - unsigned long now = jiffies; - unsigned long next_credit = - netif->credit_timeout.expires + - msecs_to_jiffies(netif->credit_usec / 1000); - - /* Timer could already be pending in some rare cases. */ - if ( timer_pending(&netif->credit_timeout) ) - break; - - /* Already passed the point at which we can replenish credit? */ - if ( time_after_eq(now, next_credit) ) - { - netif->credit_timeout.expires = now; - netif->remaining_credit = netif->credit_bytes; - } - - /* Still too big to send right now? Then set a timer callback. */ - if ( txreq.size > netif->remaining_credit ) - { - netif->remaining_credit = 0; - netif->credit_timeout.expires = next_credit; - netif->credit_timeout.data = (unsigned long)netif; - netif->credit_timeout.function = tx_credit_callback; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - add_timer_on(&netif->credit_timeout, smp_processor_id()); -#else - add_timer(&netif->credit_timeout); -#endif - break; - } - } - netif->remaining_credit -= txreq.size; - - /* - * Why the barrier? It ensures that the frontend sees updated req_cons - * before we check for more work to schedule. - */ - netif->tx->req_cons = ++netif->tx_req_cons; - mb(); - - netif_schedule_work(netif); - - if ( unlikely(txreq.size < ETH_HLEN) || - unlikely(txreq.size > ETH_FRAME_LEN) ) - { - DPRINTK("Bad packet size: %d\n", txreq.size); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); - continue; - } - - /* No crossing a page boundary as the payload mustn't fragment. */ - if ( unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >= PAGE_SIZE) ) - { - DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n", - txreq.addr, txreq.size, - (txreq.addr &~PAGE_MASK) + txreq.size); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); - continue; - } - - pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - - data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size; - - if ( unlikely((skb = alloc_skb(data_len+16, GFP_ATOMIC)) == NULL) ) - { - DPRINTK("Can't allocate a skb in start_xmit.\n"); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); - break; - } - - /* Packets passed to netif_rx() must have some headroom. */ - skb_reserve(skb, 16); - - mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain; - mcl[0].args[0] = MMAP_VADDR(pending_idx); - mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL; - mcl[0].args[2] = 0; - mcl[0].args[3] = netif->domid; - mcl++; - - memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq)); - pending_tx_info[pending_idx].netif = netif; - *((u16 *)skb->data) = pending_idx; - - __skb_queue_tail(&tx_queue, skb); - - pending_cons++; - - /* Filled the batch queue? */ - if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) ) - break; - } - - if ( mcl == tx_mcl ) - return; - - if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) ) - BUG(); - - mcl = tx_mcl; - while ( (skb = __skb_dequeue(&tx_queue)) != NULL ) - { - pending_idx = *((u16 *)skb->data); - netif = pending_tx_info[pending_idx].netif; - memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq)); - - /* Check the remap error code. */ - if ( unlikely(mcl[0].args[5] != 0) ) - { - DPRINTK("Bad page frame\n"); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); - kfree_skb(skb); - mcl++; - pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; - continue; - } - - phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] = - FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT); - - data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size; - - __skb_put(skb, data_len); - memcpy(skb->data, - (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)), - data_len); - - if ( data_len < txreq.size ) - { - /* Append the packet payload as a fragment. */ - skb_shinfo(skb)->frags[0].page = - virt_to_page(MMAP_VADDR(pending_idx)); - skb_shinfo(skb)->frags[0].size = txreq.size - data_len; - skb_shinfo(skb)->frags[0].page_offset = - (txreq.addr + data_len) & ~PAGE_MASK; - skb_shinfo(skb)->nr_frags = 1; - } - else - { - /* Schedule a response immediately. */ - netif_idx_release(pending_idx); - } - - skb->data_len = txreq.size - data_len; - skb->len += skb->data_len; - - skb->dev = netif->dev; - skb->protocol = eth_type_trans(skb, skb->dev); - - netif->stats.rx_bytes += txreq.size; - netif->stats.rx_packets++; - - netif_rx(skb); - netif->dev->last_rx = jiffies; - - mcl++; - } + gnttab_unmap_grant_ref_t *gop; + u16 pending_idx; + PEND_RING_IDX dc, dp; + netif_t *netif; + int ret; + + dc = dealloc_cons; + dp = dealloc_prod; + + /* Ensure we see all indexes enqueued by netif_idx_release(). */ + smp_rmb(); + + /* + * Free up any grants we have finished using + */ + gop = tx_unmap_ops; + while (dc != dp) { + pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; + gnttab_set_unmap_op(gop, MMAP_VADDR(pending_idx), + GNTMAP_host_map, + grant_tx_handle[pending_idx]); + gop++; + } + ret = HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops); + BUG_ON(ret); + + while (dealloc_cons != dp) { + pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; + + netif = pending_tx_info[pending_idx].netif; + + make_tx_response(netif, &pending_tx_info[pending_idx].req, + NETIF_RSP_OKAY); + + pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; + + netif_put(netif); + } } -static void netif_idx_release(u16 pending_idx) +static void netbk_tx_err(netif_t *netif, netif_tx_request_t *txp, RING_IDX end) { - static spinlock_t _lock = SPIN_LOCK_UNLOCKED; - unsigned long flags; - - spin_lock_irqsave(&_lock, flags); - dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx; - spin_unlock_irqrestore(&_lock, flags); - - tasklet_schedule(&net_tx_tasklet); + RING_IDX cons = netif->tx.req_cons; + + do { + make_tx_response(netif, txp, NETIF_RSP_ERROR); + if (cons >= end) + break; + txp = RING_GET_REQUEST(&netif->tx, cons++); + } while (1); + netif->tx.req_cons = cons; + netif_schedule_work(netif); + netif_put(netif); } -static void netif_page_release(struct page *page) +static int netbk_count_requests(netif_t *netif, netif_tx_request_t *txp, + int work_to_do) { - u16 pending_idx = page - virt_to_page(mmap_vstart); - - /* Ready for next use. */ - set_page_count(page, 1); - - netif_idx_release(pending_idx); + netif_tx_request_t *first = txp; + RING_IDX cons = netif->tx.req_cons; + int frags = 0; + + while (txp->flags & NETTXF_more_data) { + if (frags >= work_to_do) { + DPRINTK("Need more frags\n"); + return -frags; + } + + txp = RING_GET_REQUEST(&netif->tx, cons + frags); + if (txp->size > first->size) { + DPRINTK("Frags galore\n"); + return -frags; + } + + first->size -= txp->size; + frags++; + + if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { + DPRINTK("txp->offset: %x, size: %u\n", + txp->offset, txp->size); + return -frags; + } + } + + return frags; } -irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs) +static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif, + struct sk_buff *skb, + gnttab_map_grant_ref_t *mop) { - netif_t *netif = dev_id; - if ( tx_work_exists(netif) ) - { - add_to_net_schedule_list_tail(netif); - maybe_schedule_tx_action(); - } - return IRQ_HANDLED; + struct skb_shared_info *shinfo = skb_shinfo(skb); + skb_frag_t *frags = shinfo->frags; + netif_tx_request_t *txp; + unsigned long pending_idx = *((u16 *)skb->data); + RING_IDX cons = netif->tx.req_cons; + int i, start; + + /* Skip first skb fragment if it is on same page as header fragment. */ + start = ((unsigned long)shinfo->frags[0].page == pending_idx); + + for (i = start; i < shinfo->nr_frags; i++) { + txp = RING_GET_REQUEST(&netif->tx, cons++); + pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)]; + + gnttab_set_map_op(mop++, MMAP_VADDR(pending_idx), + GNTMAP_host_map | GNTMAP_readonly, + txp->gref, netif->domid); + + memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp)); + netif_get(netif); + pending_tx_info[pending_idx].netif = netif; + frags[i].page = (void *)pending_idx; + } + + return mop; } -static void make_tx_response(netif_t *netif, - u16 id, - s8 st) +static int netbk_tx_check_mop(struct sk_buff *skb, + gnttab_map_grant_ref_t **mopp) { - NETIF_RING_IDX i = netif->tx_resp_prod; - netif_tx_response_t *resp; + gnttab_map_grant_ref_t *mop = *mopp; + int pending_idx = *((u16 *)skb->data); + netif_t *netif = pending_tx_info[pending_idx].netif; + netif_tx_request_t *txp; + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + int i, err, start; + + /* Check status of header. */ + err = mop->status; + if (unlikely(err)) { + txp = &pending_tx_info[pending_idx].req; + make_tx_response(netif, txp, NETIF_RSP_ERROR); + pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; + netif_put(netif); + } else { + set_phys_to_machine( + __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT, + FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); + grant_tx_handle[pending_idx] = mop->handle; + } + + /* Skip first skb fragment if it is on same page as header fragment. */ + start = ((unsigned long)shinfo->frags[0].page == pending_idx); + + for (i = start; i < nr_frags; i++) { + int j, newerr; + + pending_idx = (unsigned long)shinfo->frags[i].page; + + /* Check error status: if okay then remember grant handle. */ + newerr = (++mop)->status; + if (likely(!newerr)) { + set_phys_to_machine( + __pa(MMAP_VADDR(pending_idx))>>PAGE_SHIFT, + FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT)); + grant_tx_handle[pending_idx] = mop->handle; + /* Had a previous error? Invalidate this fragment. */ + if (unlikely(err)) + netif_idx_release(pending_idx); + continue; + } + + /* Error on this fragment: respond to client with an error. */ + txp = &pending_tx_info[pending_idx].req; + make_tx_response(netif, txp, NETIF_RSP_ERROR); + pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; + netif_put(netif); + + /* Not the first error? Preceding frags already invalidated. */ + if (err) + continue; + + /* First error: invalidate header and preceding fragments. */ + pending_idx = *((u16 *)skb->data); + netif_idx_release(pending_idx); + for (j = start; j < i; j++) { + pending_idx = (unsigned long)shinfo->frags[i].page; + netif_idx_release(pending_idx); + } + + /* Remember the error: invalidate all subsequent fragments. */ + err = newerr; + } + + *mopp = mop + 1; + return err; +} - resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp; - resp->id = id; - resp->status = st; - wmb(); - netif->tx->resp_prod = netif->tx_resp_prod = ++i; +static void netbk_fill_frags(struct sk_buff *skb) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + int i; + + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = shinfo->frags + i; + netif_tx_request_t *txp; + unsigned long pending_idx; + + pending_idx = (unsigned long)frag->page; + txp = &pending_tx_info[pending_idx].req; + frag->page = virt_to_page(MMAP_VADDR(pending_idx)); + frag->size = txp->size; + frag->page_offset = txp->offset; + + skb->len += txp->size; + skb->data_len += txp->size; + skb->truesize += txp->size; + } +} - mb(); /* Update producer before checking event threshold. */ - if ( i == netif->tx->event ) - notify_via_evtchn(netif->evtchn); +int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras, + int work_to_do) +{ + struct netif_extra_info *extra; + RING_IDX cons = netif->tx.req_cons; + + do { + if (unlikely(work_to_do-- <= 0)) { + DPRINTK("Missing extra info\n"); + return -EBADR; + } + + extra = (struct netif_extra_info *) + RING_GET_REQUEST(&netif->tx, cons); + if (unlikely(!extra->type || + extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + netif->tx.req_cons = ++cons; + DPRINTK("Invalid extra type: %d\n", extra->type); + return -EINVAL; + } + + memcpy(&extras[extra->type - 1], extra, sizeof(*extra)); + netif->tx.req_cons = ++cons; + } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); + + return work_to_do; } -static int make_rx_response(netif_t *netif, - u16 id, - s8 st, - memory_t addr, - u16 size) +static int netbk_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso) { - NETIF_RING_IDX i = netif->rx_resp_prod; - netif_rx_response_t *resp; + if (!gso->u.gso.size) { + DPRINTK("GSO size must not be zero.\n"); + return -EINVAL; + } + + /* Currently only TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { + DPRINTK("Bad GSO type %d.\n", gso->u.gso.type); + return -EINVAL; + } + + skb_shinfo(skb)->gso_size = gso->u.gso.size; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp; - resp->addr = addr; - resp->id = id; - resp->status = (s16)size; - if ( st < 0 ) - resp->status = (s16)st; - wmb(); - netif->rx->resp_prod = netif->rx_resp_prod = ++i; + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; - mb(); /* Update producer before checking event threshold. */ - return (i == netif->rx->event); + return 0; } -static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs) +/* Called after netfront has transmitted */ +static void net_tx_action(unsigned long unused) { - struct list_head *ent; - netif_t *netif; - int i = 0; - - printk(KERN_ALERT "netif_schedule_list:\n"); - spin_lock_irq(&net_schedule_list_lock); + struct list_head *ent; + struct sk_buff *skb; + netif_t *netif; + netif_tx_request_t txreq; + struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; + u16 pending_idx; + RING_IDX i; + gnttab_map_grant_ref_t *mop; + unsigned int data_len; + int ret, work_to_do; + + if (dealloc_cons != dealloc_prod) + net_tx_action_dealloc(); + + mop = tx_map_ops; + while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) && + !list_empty(&net_schedule_list)) { + /* Get a netif from the list with work to do. */ + ent = net_schedule_list.next; + netif = list_entry(ent, netif_t, list); + netif_get(netif); + remove_from_net_schedule_list(netif); + + RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, work_to_do); + if (!work_to_do) { + netif_put(netif); + continue; + } + + i = netif->tx.req_cons; + rmb(); /* Ensure that we see the request before we copy it. */ + memcpy(&txreq, RING_GET_REQUEST(&netif->tx, i), sizeof(txreq)); + /* Credit-based scheduling. */ + if (txreq.size > netif->remaining_credit) { + unsigned long now = jiffies; + unsigned long next_credit = + netif->credit_timeout.expires + + msecs_to_jiffies(netif->credit_usec / 1000); + + /* Timer could already be pending in rare cases. */ + if (timer_pending(&netif->credit_timeout)) + break; + + /* Passed the point where we can replenish credit? */ + if (time_after_eq(now, next_credit)) { + netif->credit_timeout.expires = now; + netif->remaining_credit = netif->credit_bytes; + } + + /* Still too big to send right now? Set a callback. */ + if (txreq.size > netif->remaining_credit) { + netif->remaining_credit = 0; + netif->credit_timeout.data = + (unsigned long)netif; + netif->credit_timeout.function = + tx_credit_callback; + __mod_timer(&netif->credit_timeout, + next_credit); + break; + } + } + netif->remaining_credit -= txreq.size; + + work_to_do--; + netif->tx.req_cons = ++i; + + memset(extras, 0, sizeof(extras)); + if (txreq.flags & NETTXF_extra_info) { + work_to_do = netbk_get_extras(netif, extras, + work_to_do); + i = netif->tx.req_cons; + if (unlikely(work_to_do < 0)) { + netbk_tx_err(netif, &txreq, i); + continue; + } + } + + ret = netbk_count_requests(netif, &txreq, work_to_do); + if (unlikely(ret < 0)) { + netbk_tx_err(netif, &txreq, i - ret); + continue; + } + i += ret; + + if (unlikely(ret > MAX_SKB_FRAGS)) { + DPRINTK("Too many frags\n"); + netbk_tx_err(netif, &txreq, i); + continue; + } + + if (unlikely(txreq.size < ETH_HLEN)) { + DPRINTK("Bad packet size: %d\n", txreq.size); + netbk_tx_err(netif, &txreq, i); + continue; + } + + /* No crossing a page as the payload mustn't fragment. */ + if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { + DPRINTK("txreq.offset: %x, size: %u, end: %lu\n", + txreq.offset, txreq.size, + (txreq.offset &~PAGE_MASK) + txreq.size); + netbk_tx_err(netif, &txreq, i); + continue; + } + + pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; + + data_len = (txreq.size > PKT_PROT_LEN && + ret < MAX_SKB_FRAGS) ? + PKT_PROT_LEN : txreq.size; + + skb = alloc_skb(data_len+16, GFP_ATOMIC); + if (unlikely(skb == NULL)) { + DPRINTK("Can't allocate a skb in start_xmit.\n"); + netbk_tx_err(netif, &txreq, i); + break; + } + + /* Packets passed to netif_rx() must have some headroom. */ + skb_reserve(skb, 16); + + if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) { + struct netif_extra_info *gso; + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + if (netbk_set_skb_gso(skb, gso)) { + kfree_skb(skb); + netbk_tx_err(netif, &txreq, i); + continue; + } + } + + gnttab_set_map_op(mop, MMAP_VADDR(pending_idx), + GNTMAP_host_map | GNTMAP_readonly, + txreq.gref, netif->domid); + mop++; + + memcpy(&pending_tx_info[pending_idx].req, + &txreq, sizeof(txreq)); + pending_tx_info[pending_idx].netif = netif; + *((u16 *)skb->data) = pending_idx; + + __skb_put(skb, data_len); + + skb_shinfo(skb)->nr_frags = ret; + if (data_len < txreq.size) { + skb_shinfo(skb)->nr_frags++; + skb_shinfo(skb)->frags[0].page = + (void *)(unsigned long)pending_idx; + } + + __skb_queue_tail(&tx_queue, skb); + + pending_cons++; + + mop = netbk_get_requests(netif, skb, mop); + + netif->tx.req_cons = i; + netif_schedule_work(netif); + + if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops)) + break; + } + + if (mop == tx_map_ops) + return; + + ret = HYPERVISOR_grant_table_op( + GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops); + BUG_ON(ret); + + mop = tx_map_ops; + while ((skb = __skb_dequeue(&tx_queue)) != NULL) { + netif_tx_request_t *txp; + + pending_idx = *((u16 *)skb->data); + netif = pending_tx_info[pending_idx].netif; + txp = &pending_tx_info[pending_idx].req; + + /* Check the remap error code. */ + if (unlikely(netbk_tx_check_mop(skb, &mop))) { + printk(KERN_ALERT "#### netback grant fails\n"); + skb_shinfo(skb)->nr_frags = 0; + kfree_skb(skb); + continue; + } + + data_len = skb->len; + memcpy(skb->data, + (void *)(MMAP_VADDR(pending_idx)|txp->offset), + data_len); + if (data_len < txp->size) { + /* Append the packet payload as a fragment. */ + txp->offset += data_len; + txp->size -= data_len; + } else { + /* Schedule a response immediately. */ + netif_idx_release(pending_idx); + } + + /* + * Old frontends do not assert data_validated but we + * can infer it from csum_blank so test both flags. + */ + if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->proto_data_valid = 1; + } else { + skb->ip_summed = CHECKSUM_NONE; + skb->proto_data_valid = 0; + } + skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank); + + netbk_fill_frags(skb); + + skb->dev = netif->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + + netif->stats.rx_bytes += skb->len; + netif->stats.rx_packets++; + + netif_rx(skb); + netif->dev->last_rx = jiffies; + } +} - list_for_each ( ent, &net_schedule_list ) - { - netif = list_entry(ent, netif_t, list); - printk(KERN_ALERT " %d: private(rx_req_cons=%08x rx_resp_prod=%08x\n", - i, netif->rx_req_cons, netif->rx_resp_prod); - printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", - netif->tx_req_cons, netif->tx_resp_prod); - printk(KERN_ALERT " shared(rx_req_prod=%08x rx_resp_prod=%08x\n", - netif->rx->req_prod, netif->rx->resp_prod); - printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", - netif->rx->event, netif->tx->req_prod); - printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", - netif->tx->resp_prod, netif->tx->event); - i++; - } +static void netif_idx_release(u16 pending_idx) +{ + static DEFINE_SPINLOCK(_lock); + unsigned long flags; - spin_unlock_irq(&net_schedule_list_lock); - printk(KERN_ALERT " ** End of netif_schedule_list **\n"); + spin_lock_irqsave(&_lock, flags); + dealloc_ring[MASK_PEND_IDX(dealloc_prod)] = pending_idx; + /* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */ + smp_wmb(); + dealloc_prod++; + spin_unlock_irqrestore(&_lock, flags); - return IRQ_HANDLED; + tasklet_schedule(&net_tx_tasklet); } -static int __init netback_init(void) +static void netif_page_release(struct page *page) { - int i; - struct page *page; + u16 pending_idx = page - virt_to_page(mmap_vstart); - if ( !(xen_start_info.flags & SIF_NET_BE_DOMAIN) && - !(xen_start_info.flags & SIF_INITDOMAIN) ) - return 0; + /* Ready for next use. */ + init_page_count(page); - printk("Initialising Xen netif backend\n"); + netif_idx_release(pending_idx); +} - /* We can increase reservation by this much in net_rx_action(). */ - balloon_update_driver_allowance(NETIF_RX_RING_SIZE); +irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs) +{ + netif_t *netif = dev_id; - skb_queue_head_init(&rx_queue); - skb_queue_head_init(&tx_queue); + add_to_net_schedule_list_tail(netif); + maybe_schedule_tx_action(); - init_timer(&net_timer); - net_timer.data = 0; - net_timer.function = net_alarm; - - netif_interface_init(); + if (netif_queue_stopped(netif->dev) && !netbk_queue_full(netif)) + netif_wake_queue(netif->dev); - if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 ) - BUG(); + return IRQ_HANDLED; +} - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - { - page = virt_to_page(MMAP_VADDR(i)); - set_page_count(page, 1); - SetPageForeign(page, netif_page_release); - } +static void make_tx_response(netif_t *netif, + netif_tx_request_t *txp, + s8 st) +{ + RING_IDX i = netif->tx.rsp_prod_pvt; + netif_tx_response_t *resp; + int notify; + + resp = RING_GET_RESPONSE(&netif->tx, i); + resp->id = txp->id; + resp->status = st; + + if (txp->flags & NETTXF_extra_info) + RING_GET_RESPONSE(&netif->tx, ++i)->status = NETIF_RSP_NULL; + + netif->tx.rsp_prod_pvt = ++i; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->tx, notify); + if (notify) + notify_remote_via_irq(netif->irq); + +#ifdef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER + if (i == netif->tx.req_cons) { + int more_to_do; + RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, more_to_do); + if (more_to_do) + add_to_net_schedule_list_tail(netif); + } +#endif +} - pending_cons = 0; - pending_prod = MAX_PENDING_REQS; - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - pending_ring[i] = i; +static netif_rx_response_t *make_rx_response(netif_t *netif, + u16 id, + s8 st, + u16 offset, + u16 size, + u16 flags) +{ + RING_IDX i = netif->rx.rsp_prod_pvt; + netif_rx_response_t *resp; - spin_lock_init(&net_schedule_list_lock); - INIT_LIST_HEAD(&net_schedule_list); + resp = RING_GET_RESPONSE(&netif->rx, i); + resp->offset = offset; + resp->flags = flags; + resp->id = id; + resp->status = (s16)size; + if (st < 0) + resp->status = (s16)st; - netif_ctrlif_init(); + netif->rx.rsp_prod_pvt = ++i; - (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG), - netif_be_dbg, SA_SHIRQ, - "net-be-dbg", &netif_be_dbg); + return resp; +} - return 0; +#ifdef NETBE_DEBUG_INTERRUPT +static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs) +{ + struct list_head *ent; + netif_t *netif; + int i = 0; + + printk(KERN_ALERT "netif_schedule_list:\n"); + spin_lock_irq(&net_schedule_list_lock); + + list_for_each (ent, &net_schedule_list) { + netif = list_entry(ent, netif_t, list); + printk(KERN_ALERT " %d: private(rx_req_cons=%08x " + "rx_resp_prod=%08x\n", + i, netif->rx.req_cons, netif->rx.rsp_prod_pvt); + printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", + netif->tx.req_cons, netif->tx.rsp_prod_pvt); + printk(KERN_ALERT " shared(rx_req_prod=%08x " + "rx_resp_prod=%08x\n", + netif->rx.sring->req_prod, netif->rx.sring->rsp_prod); + printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", + netif->rx.sring->rsp_event, netif->tx.sring->req_prod); + printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", + netif->tx.sring->rsp_prod, netif->tx.sring->rsp_event); + i++; + } + + spin_unlock_irq(&net_schedule_list_lock); + printk(KERN_ALERT " ** End of netif_schedule_list **\n"); + + return IRQ_HANDLED; } +#endif -static void netback_cleanup(void) +static int __init netback_init(void) { - BUG(); + int i; + struct page *page; + + if (!is_running_on_xen()) + return -ENODEV; + + /* We can increase reservation by this much in net_rx_action(). */ + balloon_update_driver_allowance(NET_RX_RING_SIZE); + + skb_queue_head_init(&rx_queue); + skb_queue_head_init(&tx_queue); + + init_timer(&net_timer); + net_timer.data = 0; + net_timer.function = net_alarm; + + page = balloon_alloc_empty_page_range(MAX_PENDING_REQS); + if (page == NULL) + return -ENOMEM; + + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); + + for (i = 0; i < MAX_PENDING_REQS; i++) { + page = virt_to_page(MMAP_VADDR(i)); + init_page_count(page); + SetPageForeign(page, netif_page_release); + } + + pending_cons = 0; + pending_prod = MAX_PENDING_REQS; + for (i = 0; i < MAX_PENDING_REQS; i++) + pending_ring[i] = i; + + spin_lock_init(&net_schedule_list_lock); + INIT_LIST_HEAD(&net_schedule_list); + + netif_xenbus_init(); + +#ifdef NETBE_DEBUG_INTERRUPT + (void)bind_virq_to_irqhandler( + VIRQ_DEBUG, + 0, + netif_be_dbg, + SA_SHIRQ, + "net-be-dbg", + &netif_be_dbg); +#endif + + return 0; } module_init(netback_init); -module_exit(netback_cleanup); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/netfront/Makefile b/drivers/xen/netfront/Makefile index 7eb07a248..dc22829f5 100644 --- a/drivers/xen/netfront/Makefile +++ b/drivers/xen/netfront/Makefile @@ -1,2 +1,4 @@ -obj-y := netfront.o +obj-$(CONFIG_XEN_NETDEV_FRONTEND) := xennet.o + +xennet-objs := netfront.o diff --git a/drivers/xen/netfront/netfront.c b/drivers/xen/netfront/netfront.c index f72929502..ef6e134a7 100644 --- a/drivers/xen/netfront/netfront.c +++ b/drivers/xen/netfront/netfront.c @@ -1,21 +1,25 @@ /****************************************************************************** * Virtual network driver for conversing with remote driver backends. - * - * Copyright (c) 2002-2004, K A Fraser - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * + * + * Copyright (c) 2002-2005, K A Fraser + * Copyright (c) 2005, XenSource Ltd + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -39,214 +43,422 @@ #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 -#ifndef __GFP_NOWARN -#define __GFP_NOWARN 0 -#endif -#define alloc_xen_skb(_l) __dev_alloc_skb((_l), GFP_ATOMIC|__GFP_NOWARN) +#define RX_COPY_THRESHOLD 256 -#define init_skb_shinfo(_skb) \ - do { \ - atomic_set(&(skb_shinfo(_skb)->dataref), 1); \ - skb_shinfo(_skb)->nr_frags = 0; \ - skb_shinfo(_skb)->frag_list = NULL; \ - } while (0) +#define GRANT_INVALID_REF 0 -/* Allow headroom on each rx pkt for Ethernet header, alignment padding, ... */ -#define RX_HEADROOM 200 +#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE) +#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE) -/* - * If the backend driver is pipelining transmit requests then we can be very - * aggressive in avoiding new-packet notifications -- only need to send a - * notification if there are no outstanding unreceived responses. - * If the backend may be buffering our transmit buffers for any reason then we - * are rather more conservative. - */ -#ifdef CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER -#define TX_TEST_IDX resp_prod /* aggressive: any outstanding responses? */ -#else -#define TX_TEST_IDX req_cons /* conservative: not seen all our requests? */ -#endif +struct netfront_info { + struct list_head list; + struct net_device *netdev; -static void network_tx_buf_gc(struct net_device *dev); -static void network_alloc_rx_buffers(struct net_device *dev); + struct net_device_stats stats; -static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE]; -static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1]; -static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; + struct netif_tx_front_ring tx; + struct netif_rx_front_ring rx; -static struct list_head dev_list; + spinlock_t tx_lock; + spinlock_t rx_lock; -struct net_private -{ - struct list_head list; - struct net_device *dev; - - struct net_device_stats stats; - NETIF_RING_IDX rx_resp_cons, tx_resp_cons; - unsigned int tx_full; - - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; - - spinlock_t tx_lock; - spinlock_t rx_lock; - - unsigned int handle; - unsigned int evtchn; - unsigned int irq; - - /* What is the status of our connection to the remote backend? */ -#define BEST_CLOSED 0 -#define BEST_DISCONNECTED 1 -#define BEST_CONNECTED 2 - unsigned int backend_state; - - /* Is this interface open or closed (down or up)? */ -#define UST_CLOSED 0 -#define UST_OPEN 1 - unsigned int user_state; - - /* Receive-ring batched refills. */ + unsigned int handle; + unsigned int evtchn, irq; + + /* Receive-ring batched refills. */ #define RX_MIN_TARGET 8 -#define RX_MAX_TARGET NETIF_RX_RING_SIZE - int rx_target; - struct sk_buff_head rx_batch; - - /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. - */ - struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; +#define RX_DFL_MIN_TARGET 64 +#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) + unsigned rx_min_target, rx_max_target, rx_target; + struct sk_buff_head rx_batch; + + struct timer_list rx_refill_timer; + + /* + * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs + * is an index into a chain of free entries. + */ + struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1]; + struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; + +#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) + grant_ref_t gref_tx_head; + grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1]; + grant_ref_t gref_rx_head; + grant_ref_t grant_rx_ref[NET_TX_RING_SIZE]; + + struct xenbus_device *xbdev; + int tx_ring_ref; + int rx_ring_ref; + u8 mac[ETH_ALEN]; + + unsigned long rx_pfn_array[NET_RX_RING_SIZE]; + struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1]; + struct mmu_update rx_mmu[NET_RX_RING_SIZE]; }; -/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ -#define ADD_ID_TO_FREELIST(_list, _id) \ - (_list)[(_id)] = (_list)[0]; \ - (_list)[0] = (void *)(unsigned long)(_id); -#define GET_ID_FROM_FREELIST(_list) \ - ({ unsigned long _id = (unsigned long)(_list)[0]; \ - (_list)[0] = (_list)[_id]; \ - (unsigned short)_id; }) - -static char *status_name[] = { - [NETIF_INTERFACE_STATUS_CLOSED] = "closed", - [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected", - [NETIF_INTERFACE_STATUS_CONNECTED] = "connected", - [NETIF_INTERFACE_STATUS_CHANGED] = "changed", +struct netfront_rx_info { + struct netif_rx_response rx; + struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; }; -static char *be_state_name[] = { - [BEST_CLOSED] = "closed", - [BEST_DISCONNECTED] = "disconnected", - [BEST_CONNECTED] = "connected", -}; +/* + * Access macros for acquiring freeing slots in tx_skbs[]. + */ -#if DEBUG -#define DPRINTK(fmt, args...) \ - printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif -#define IPRINTK(fmt, args...) \ - printk(KERN_INFO "xen_net: " fmt, ##args) -#define WPRINTK(fmt, args...) \ - printk(KERN_WARNING "xen_net: " fmt, ##args) +static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id) +{ + list[id] = list[0]; + list[0] = (void *)(unsigned long)id; +} -static struct net_device *find_dev_by_handle(unsigned int handle) +static inline unsigned short get_id_from_freelist(struct sk_buff **list) { - struct list_head *ent; - struct net_private *np; - list_for_each (ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - if (np->handle == handle) - return np->dev; - } - return NULL; + unsigned int id = (unsigned int)(unsigned long)list[0]; + list[0] = list[id]; + return id; } -/** Network interface info. */ -struct netif_ctrl { - /** Number of interfaces. */ - int interface_n; - /** Number of connected interfaces. */ - int connected_n; - /** Error code. */ - int err; - int up; -}; +static inline int xennet_rxidx(RING_IDX idx) +{ + return idx & (NET_RX_RING_SIZE - 1); +} + +static inline struct sk_buff *xennet_get_rx_skb(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + struct sk_buff *skb = np->rx_skbs[i]; + np->rx_skbs[i] = NULL; + return skb; +} + +static inline grant_ref_t xennet_get_rx_ref(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + grant_ref_t ref = np->grant_rx_ref[i]; + np->grant_rx_ref[i] = GRANT_INVALID_REF; + return ref; +} -static struct netif_ctrl netctrl; +#define DPRINTK(fmt, args...) \ + pr_debug("netfront (%s:%d) " fmt, \ + __FUNCTION__, __LINE__, ##args) +#define IPRINTK(fmt, args...) \ + printk(KERN_INFO "netfront: " fmt, ##args) +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "netfront: " fmt, ##args) + +static int talk_to_backend(struct xenbus_device *, struct netfront_info *); +static int setup_device(struct xenbus_device *, struct netfront_info *); +static struct net_device *create_netdev(int, struct xenbus_device *); + +static void netfront_closing(struct xenbus_device *); + +static void end_access(int, void *); +static void netif_disconnect_backend(struct netfront_info *); +static void close_netdev(struct netfront_info *); +static void netif_free(struct netfront_info *); + +static void network_connect(struct net_device *); +static void network_tx_buf_gc(struct net_device *); +static void network_alloc_rx_buffers(struct net_device *); +static int send_fake_arp(struct net_device *); + +static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs); + +#ifdef CONFIG_SYSFS +static int xennet_sysfs_addif(struct net_device *netdev); +static void xennet_sysfs_delif(struct net_device *netdev); +#else /* !CONFIG_SYSFS */ +#define xennet_sysfs_addif(dev) (0) +#define xennet_sysfs_delif(dev) do { } while(0) +#endif -static void netctrl_init(void) +static inline int xennet_can_sg(struct net_device *dev) { - memset(&netctrl, 0, sizeof(netctrl)); - netctrl.up = NETIF_DRIVER_STATUS_DOWN; + return dev->features & NETIF_F_SG; } -/** Get or set a network interface error. +/** + * Entry point to this code when a new device is created. Allocate the basic + * structures and the ring buffers for communication with the backend, and + * inform the backend of the appropriate details for those. Switch to + * Connected state. */ -static int netctrl_err(int err) +static int __devinit netfront_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) { - if ((err < 0) && !netctrl.err) - netctrl.err = err; - return netctrl.err; + int err; + struct net_device *netdev; + struct netfront_info *info; + unsigned int handle; + + err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%u", &handle); + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading handle"); + return err; + } + + netdev = create_netdev(handle, dev); + if (IS_ERR(netdev)) { + err = PTR_ERR(netdev); + xenbus_dev_fatal(dev, err, "creating netdev"); + return err; + } + + info = netdev_priv(netdev); + dev->dev.driver_data = info; + + err = talk_to_backend(dev, info); + if (err) { + xennet_sysfs_delif(info->netdev); + unregister_netdev(netdev); + free_netdev(netdev); + dev->dev.driver_data = NULL; + return err; + } + + return 0; } -/** Test if all network interfaces are connected. - * - * @return 1 if all connected, 0 if not, negative error code otherwise + +/** + * We are reconnecting to the backend, due to a suspend/resume, or a backend + * driver restart. We tear down our netif structure and recreate it, but + * leave the device-layer structures intact so that this is transparent to the + * rest of the kernel. */ -static int netctrl_connected(void) +static int netfront_resume(struct xenbus_device *dev) { - int ok; + struct netfront_info *info = dev->dev.driver_data; - if (netctrl.err) - ok = netctrl.err; - else if (netctrl.up == NETIF_DRIVER_STATUS_UP) - ok = (netctrl.connected_n == netctrl.interface_n); - else - ok = 0; + DPRINTK("%s\n", dev->nodename); - return ok; + netif_disconnect_backend(info); + return talk_to_backend(dev, info); } -/** Count the connected network interfaces. - * - * @return connected count +static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[]) +{ + char *s, *e, *macstr; + int i; + + macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL); + if (IS_ERR(macstr)) + return PTR_ERR(macstr); + + for (i = 0; i < ETH_ALEN; i++) { + mac[i] = simple_strtoul(s, &e, 16); + if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) { + kfree(macstr); + return -ENOENT; + } + s = e+1; + } + + kfree(macstr); + return 0; +} + +/* Common code used when first setting up, and when resuming. */ +static int talk_to_backend(struct xenbus_device *dev, + struct netfront_info *info) +{ + const char *message; + struct xenbus_transaction xbt; + int err; + + err = xen_net_read_mac(dev, info->mac); + if (err) { + xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); + goto out; + } + + /* Create shared ring, alloc event channel. */ + err = setup_device(dev, info); + if (err) + goto out; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + goto destroy_ring; + } + + err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u", + info->tx_ring_ref); + if (err) { + message = "writing tx ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u", + info->rx_ring_ref); + if (err) { + message = "writing rx ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(xbt, dev->nodename, + "event-channel", "%u", info->evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1); + if (err) { + message = "writing feature-rx-notify"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1); + if (err) { + message = "writing feature-sg"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1); + if (err) { + message = "writing feature-gso-tcpv4"; + goto abort_transaction; + } + + err = xenbus_transaction_end(xbt, 0); + if (err) { + if (err == -EAGAIN) + goto again; + xenbus_dev_fatal(dev, err, "completing transaction"); + goto destroy_ring; + } + + return 0; + + abort_transaction: + xenbus_transaction_end(xbt, 1); + xenbus_dev_fatal(dev, err, "%s", message); + destroy_ring: + netif_free(info); + out: + return err; +} + + +static int setup_device(struct xenbus_device *dev, struct netfront_info *info) +{ + struct netif_tx_sring *txs; + struct netif_rx_sring *rxs; + int err; + struct net_device *netdev = info->netdev; + + info->tx_ring_ref = GRANT_INVALID_REF; + info->rx_ring_ref = GRANT_INVALID_REF; + info->rx.sring = NULL; + info->tx.sring = NULL; + info->irq = 0; + + txs = (struct netif_tx_sring *)get_zeroed_page(GFP_KERNEL); + if (!txs) { + err = -ENOMEM; + xenbus_dev_fatal(dev, err, "allocating tx ring page"); + goto fail; + } + SHARED_RING_INIT(txs); + FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); + + err = xenbus_grant_ring(dev, virt_to_mfn(txs)); + if (err < 0) { + free_page((unsigned long)txs); + goto fail; + } + info->tx_ring_ref = err; + + rxs = (struct netif_rx_sring *)get_zeroed_page(GFP_KERNEL); + if (!rxs) { + err = -ENOMEM; + xenbus_dev_fatal(dev, err, "allocating rx ring page"); + goto fail; + } + SHARED_RING_INIT(rxs); + FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE); + + err = xenbus_grant_ring(dev, virt_to_mfn(rxs)); + if (err < 0) { + free_page((unsigned long)rxs); + goto fail; + } + info->rx_ring_ref = err; + + err = xenbus_alloc_evtchn(dev, &info->evtchn); + if (err) + goto fail; + + memcpy(netdev->dev_addr, info->mac, ETH_ALEN); + err = bind_evtchn_to_irqhandler(info->evtchn, netif_int, + SA_SAMPLE_RANDOM, netdev->name, netdev); + if (err < 0) + goto fail; + info->irq = err; + return 0; + + fail: + netif_free(info); + return err; +} + + +/** + * Callback received when the backend's state changes. */ -static int netctrl_connected_count(void) +static void backend_changed(struct xenbus_device *dev, + enum xenbus_state backend_state) { - - struct list_head *ent; - struct net_private *np; - unsigned int connected; - - connected = 0; - - list_for_each(ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - if (np->backend_state == BEST_CONNECTED) - connected++; - } - - netctrl.connected_n = connected; - DPRINTK("> connected_n=%d interface_n=%d\n", - netctrl.connected_n, netctrl.interface_n); - return connected; + struct netfront_info *np = dev->dev.driver_data; + struct net_device *netdev = np->netdev; + + DPRINTK("\n"); + + switch (backend_state) { + case XenbusStateInitialising: + case XenbusStateInitialised: + case XenbusStateConnected: + case XenbusStateUnknown: + case XenbusStateClosed: + break; + + case XenbusStateInitWait: + network_connect(netdev); + xenbus_switch_state(dev, XenbusStateConnected); + (void)send_fake_arp(netdev); + break; + + case XenbusStateClosing: + netfront_closing(dev); + break; + } } + /** Send a packet on a net device to encourage switches to learn the * MAC. We send a fake ARP request. * @@ -255,1046 +467,1375 @@ static int netctrl_connected_count(void) */ static int send_fake_arp(struct net_device *dev) { - struct sk_buff *skb; - u32 src_ip, dst_ip; + struct sk_buff *skb; + u32 src_ip, dst_ip; - dst_ip = INADDR_BROADCAST; - src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK); + dst_ip = INADDR_BROADCAST; + src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK); - /* No IP? Then nothing to do. */ - if (src_ip == 0) - return 0; + /* No IP? Then nothing to do. */ + if (src_ip == 0) + return 0; - skb = arp_create(ARPOP_REPLY, ETH_P_ARP, - dst_ip, dev, src_ip, - /*dst_hw*/ NULL, /*src_hw*/ NULL, - /*target_hw*/ dev->dev_addr); - if (skb == NULL) - return -ENOMEM; + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, + dst_ip, dev, src_ip, + /*dst_hw*/ NULL, /*src_hw*/ NULL, + /*target_hw*/ dev->dev_addr); + if (skb == NULL) + return -ENOMEM; - return dev_queue_xmit(skb); + return dev_queue_xmit(skb); } + static int network_open(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); + struct netfront_info *np = netdev_priv(dev); + + memset(&np->stats, 0, sizeof(np->stats)); - memset(&np->stats, 0, sizeof(np->stats)); + network_alloc_rx_buffers(dev); + np->rx.sring->rsp_event = np->rx.rsp_cons + 1; - np->user_state = UST_OPEN; + if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) + netif_rx_schedule(dev); - network_alloc_rx_buffers(dev); - np->rx->event = np->rx_resp_cons + 1; + netif_start_queue(dev); - netif_start_queue(dev); + return 0; +} - return 0; +static inline int netfront_tx_slot_available(struct netfront_info *np) +{ + return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 2; +} + +static inline void network_maybe_wake_tx(struct net_device *dev) +{ + struct netfront_info *np = netdev_priv(dev); + + if (unlikely(netif_queue_stopped(dev)) && + netfront_tx_slot_available(np) && + likely(netif_running(dev))) + netif_wake_queue(dev); } static void network_tx_buf_gc(struct net_device *dev) { - NETIF_RING_IDX i, prod; - unsigned short id; - struct net_private *np = netdev_priv(dev); - struct sk_buff *skb; - - if (np->backend_state != BEST_CONNECTED) - return; - - do { - prod = np->tx->resp_prod; - rmb(); /* Ensure we see responses up to 'rp'. */ - - for (i = np->tx_resp_cons; i != prod; i++) { - id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; - skb = np->tx_skbs[id]; - ADD_ID_TO_FREELIST(np->tx_skbs, id); - dev_kfree_skb_irq(skb); - } - - np->tx_resp_cons = prod; - - /* - * Set a new event, then check for race with update of tx_cons. Note - * that it is essential to schedule a callback, no matter how few - * buffers are pending. Even if there is space in the transmit ring, - * higher layers may be blocked because too much data is outstanding: - * in such cases notification from Xen is likely to be the only kick - * that we'll get. - */ - np->tx->event = - prod + ((np->tx->req_prod - prod) >> 1) + 1; - mb(); - } while (prod != np->tx->resp_prod); - - if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) { - np->tx_full = 0; - if (np->user_state == UST_OPEN) - netif_wake_queue(dev); - } + RING_IDX cons, prod; + unsigned short id; + struct netfront_info *np = netdev_priv(dev); + struct sk_buff *skb; + + if (unlikely(!netif_carrier_ok(dev))) + return; + + do { + prod = np->tx.sring->rsp_prod; + rmb(); /* Ensure we see responses up to 'rp'. */ + + for (cons = np->tx.rsp_cons; cons != prod; cons++) { + struct netif_tx_response *txrsp; + + txrsp = RING_GET_RESPONSE(&np->tx, cons); + if (txrsp->status == NETIF_RSP_NULL) + continue; + + id = txrsp->id; + skb = np->tx_skbs[id]; + if (unlikely(gnttab_query_foreign_access( + np->grant_tx_ref[id]) != 0)) { + printk(KERN_ALERT "network_tx_buf_gc: warning " + "-- grant still in use by backend " + "domain.\n"); + BUG(); + } + gnttab_end_foreign_access_ref( + np->grant_tx_ref[id], GNTMAP_readonly); + gnttab_release_grant_reference( + &np->gref_tx_head, np->grant_tx_ref[id]); + np->grant_tx_ref[id] = GRANT_INVALID_REF; + add_id_to_freelist(np->tx_skbs, id); + dev_kfree_skb_irq(skb); + } + + np->tx.rsp_cons = prod; + + /* + * Set a new event, then check for race with update of tx_cons. + * Note that it is essential to schedule a callback, no matter + * how few buffers are pending. Even if there is space in the + * transmit ring, higher layers may be blocked because too much + * data is outstanding: in such cases notification from Xen is + * likely to be the only kick that we'll get. + */ + np->tx.sring->rsp_event = + prod + ((np->tx.sring->req_prod - prod) >> 1) + 1; + mb(); + } while ((cons == prod) && (prod != np->tx.sring->rsp_prod)); + + network_maybe_wake_tx(dev); +} + + +static void rx_refill_timeout(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + netif_rx_schedule(dev); } static void network_alloc_rx_buffers(struct net_device *dev) { - unsigned short id; - struct net_private *np = netdev_priv(dev); - struct sk_buff *skb; - int i, batch_target; - NETIF_RING_IDX req_prod = np->rx->req_prod; - - if (unlikely(np->backend_state != BEST_CONNECTED)) - return; - - /* - * Allocate skbuffs greedily, even though we batch updates to the - * receive ring. This creates a less bursty demand on the memory allocator, - * so should reduce the chance of failed allocation requests both for - * ourself and for other kernel subsystems. - */ - batch_target = np->rx_target - (req_prod - np->rx_resp_cons); - for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { - if (unlikely((skb = alloc_xen_skb(dev->mtu + RX_HEADROOM)) == NULL)) - break; - __skb_queue_tail(&np->rx_batch, skb); - } - - /* Is the batch large enough to be worthwhile? */ - if (i < (np->rx_target/2)) - return; - - for (i = 0; ; i++) { - if ((skb = __skb_dequeue(&np->rx_batch)) == NULL) - break; - - skb->dev = dev; - - id = GET_ID_FROM_FREELIST(np->rx_skbs); - - np->rx_skbs[id] = skb; - - np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id; - - rx_pfn_array[i] = virt_to_machine(skb->head) >> PAGE_SHIFT; - - /* Remove this page from pseudo phys map before passing back to Xen. */ - phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] - = INVALID_P2M_ENTRY; - - rx_mcl[i].op = __HYPERVISOR_update_va_mapping; - rx_mcl[i].args[0] = (unsigned long)skb->head; - rx_mcl[i].args[1] = 0; - rx_mcl[i].args[2] = 0; - } - - /* After all PTEs have been zapped we blow away stale TLB entries. */ - rx_mcl[i-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL; - - /* Give away a batch of pages. */ - rx_mcl[i].op = __HYPERVISOR_dom_mem_op; - rx_mcl[i].args[0] = MEMOP_decrease_reservation; - rx_mcl[i].args[1] = (unsigned long)rx_pfn_array; - rx_mcl[i].args[2] = (unsigned long)i; - rx_mcl[i].args[3] = 0; - rx_mcl[i].args[4] = DOMID_SELF; - - /* Tell the ballon driver what is going on. */ - balloon_update_driver_allowance(i); - - /* Zap PTEs and give away pages in one big multicall. */ - (void)HYPERVISOR_multicall(rx_mcl, i+1); - - /* Check return status of HYPERVISOR_dom_mem_op(). */ - if (unlikely(rx_mcl[i].args[5] != i)) - panic("Unable to reduce memory reservation\n"); - - /* Above is a suitable barrier to ensure backend will see requests. */ - np->rx->req_prod = req_prod + i; - - /* Adjust our floating fill target if we risked running out of buffers. */ - if (((req_prod - np->rx->resp_prod) < (np->rx_target / 4)) && - ((np->rx_target *= 2) > RX_MAX_TARGET)) - np->rx_target = RX_MAX_TARGET; + unsigned short id; + struct netfront_info *np = netdev_priv(dev); + struct sk_buff *skb; + struct page *page; + int i, batch_target, notify; + RING_IDX req_prod = np->rx.req_prod_pvt; + struct xen_memory_reservation reservation; + grant_ref_t ref; + unsigned long pfn; + void *vaddr; + + if (unlikely(!netif_carrier_ok(dev))) + return; + + /* + * Allocate skbuffs greedily, even though we batch updates to the + * receive ring. This creates a less bursty demand on the memory + * allocator, so should reduce the chance of failed allocation requests + * both for ourself and for other kernel subsystems. + */ + batch_target = np->rx_target - (req_prod - np->rx.rsp_cons); + for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { + /* + * Allocate an skb and a page. Do not use __dev_alloc_skb as + * that will allocate page-sized buffers which is not + * necessary here. + * 16 bytes added as necessary headroom for netif_receive_skb. + */ + skb = alloc_skb(RX_COPY_THRESHOLD + 16, + GFP_ATOMIC | __GFP_NOWARN); + if (unlikely(!skb)) + goto no_skb; + + page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) { + kfree_skb(skb); +no_skb: + /* Any skbuffs queued for refill? Force them out. */ + if (i != 0) + goto refill; + /* Could not allocate any skbuffs. Try again later. */ + mod_timer(&np->rx_refill_timer, + jiffies + (HZ/10)); + break; + } + + skb_reserve(skb, 16); /* mimic dev_alloc_skb() */ + skb_shinfo(skb)->frags[0].page = page; + skb_shinfo(skb)->nr_frags = 1; + __skb_queue_tail(&np->rx_batch, skb); + } + + /* Is the batch large enough to be worthwhile? */ + if (i < (np->rx_target/2)) { + if (req_prod > np->rx.sring->req_prod) + goto push; + return; + } + + /* Adjust our fill target if we risked running out of buffers. */ + if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) && + ((np->rx_target *= 2) > np->rx_max_target)) + np->rx_target = np->rx_max_target; + + refill: + for (i = 0; ; i++) { + if ((skb = __skb_dequeue(&np->rx_batch)) == NULL) + break; + + skb->dev = dev; + + id = xennet_rxidx(req_prod + i); + + BUG_ON(np->rx_skbs[id]); + np->rx_skbs[id] = skb; + + RING_GET_REQUEST(&np->rx, req_prod + i)->id = id; + ref = gnttab_claim_grant_reference(&np->gref_rx_head); + BUG_ON((signed short)ref < 0); + np->grant_rx_ref[id] = ref; + + pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page); + vaddr = page_address(skb_shinfo(skb)->frags[0].page); + + gnttab_grant_foreign_transfer_ref(ref, + np->xbdev->otherend_id, pfn); + RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref; + np->rx_pfn_array[i] = pfn_to_mfn(pfn); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Remove this page before passing back to Xen. */ + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + MULTI_update_va_mapping(np->rx_mcl+i, + (unsigned long)vaddr, + __pte(0), 0); + } + } + + /* Tell the ballon driver what is going on. */ + balloon_update_driver_allowance(i); + + set_xen_guest_handle(reservation.extent_start, np->rx_pfn_array); + reservation.nr_extents = i; + reservation.extent_order = 0; + reservation.address_bits = 0; + reservation.domid = DOMID_SELF; + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* After all PTEs have been zapped, flush the TLB. */ + np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = + UVMF_TLB_FLUSH|UVMF_ALL; + + /* Give away a batch of pages. */ + np->rx_mcl[i].op = __HYPERVISOR_memory_op; + np->rx_mcl[i].args[0] = XENMEM_decrease_reservation; + np->rx_mcl[i].args[1] = (unsigned long)&reservation; + + /* Zap PTEs and give away pages in one big multicall. */ + (void)HYPERVISOR_multicall(np->rx_mcl, i+1); + + /* Check return status of HYPERVISOR_memory_op(). */ + if (unlikely(np->rx_mcl[i].result != i)) + panic("Unable to reduce memory reservation\n"); + } else + if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation) != i) + panic("Unable to reduce memory reservation\n"); + + /* Above is a suitable barrier to ensure backend will see requests. */ + np->rx.req_prod_pvt = req_prod + i; + push: + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify); + if (notify) + notify_remote_via_irq(np->irq); } +static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, + struct netif_tx_request *tx) +{ + struct netfront_info *np = netdev_priv(dev); + char *data = skb->data; + unsigned long mfn; + RING_IDX prod = np->tx.req_prod_pvt; + int frags = skb_shinfo(skb)->nr_frags; + unsigned int offset = offset_in_page(data); + unsigned int len = skb_headlen(skb); + unsigned int id; + grant_ref_t ref; + int i; + + while (len > PAGE_SIZE - offset) { + tx->size = PAGE_SIZE - offset; + tx->flags |= NETTXF_more_data; + len -= tx->size; + data += tx->size; + offset = 0; + + id = get_id_from_freelist(np->tx_skbs); + np->tx_skbs[id] = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = virt_to_mfn(data); + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = len; + tx->flags = 0; + } + + for (i = 0; i < frags; i++) { + skb_frag_t *frag = skb_shinfo(skb)->frags + i; + + tx->flags |= NETTXF_more_data; + + id = get_id_from_freelist(np->tx_skbs); + np->tx_skbs[id] = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = pfn_to_mfn(page_to_pfn(frag->page)); + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = frag->page_offset; + tx->size = frag->size; + tx->flags = 0; + } + + np->tx.req_prod_pvt = prod; +} static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) { - unsigned short id; - struct net_private *np = netdev_priv(dev); - netif_tx_request_t *tx; - NETIF_RING_IDX i; + unsigned short id; + struct netfront_info *np = netdev_priv(dev); + struct netif_tx_request *tx; + struct netif_extra_info *extra; + char *data = skb->data; + RING_IDX i; + grant_ref_t ref; + unsigned long mfn; + int notify; + int frags = skb_shinfo(skb)->nr_frags; + unsigned int offset = offset_in_page(data); + unsigned int len = skb_headlen(skb); + + frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE; + if (unlikely(frags > MAX_SKB_FRAGS + 1)) { + printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", + frags); + dump_stack(); + goto drop; + } + + spin_lock_irq(&np->tx_lock); + + if (unlikely(!netif_carrier_ok(dev) || + (frags > 1 && !xennet_can_sg(dev)) || + netif_needs_gso(dev, skb))) { + spin_unlock_irq(&np->tx_lock); + goto drop; + } + + i = np->tx.req_prod_pvt; + + id = get_id_from_freelist(np->tx_skbs); + np->tx_skbs[id] = skb; + + tx = RING_GET_REQUEST(&np->tx, i); + + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + mfn = virt_to_mfn(data); + gnttab_grant_foreign_access_ref( + ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly); + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = len; + + tx->flags = 0; + extra = NULL; + + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ + tx->flags |= NETTXF_csum_blank | NETTXF_data_validated; + if (skb->proto_data_valid) /* remote but checksummed? */ + tx->flags |= NETTXF_data_validated; + + if (skb_shinfo(skb)->gso_size) { + struct netif_extra_info *gso = (struct netif_extra_info *) + RING_GET_REQUEST(&np->tx, ++i); + + if (extra) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + tx->flags |= NETTXF_extra_info; + + gso->u.gso.size = skb_shinfo(skb)->gso_size; + gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + gso->u.gso.pad = 0; + gso->u.gso.features = 0; + + gso->type = XEN_NETIF_EXTRA_TYPE_GSO; + gso->flags = 0; + extra = gso; + } + + np->tx.req_prod_pvt = i + 1; + + xennet_make_frags(skb, dev, tx); + tx->size = skb->len; + + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify); + if (notify) + notify_remote_via_irq(np->irq); + + network_tx_buf_gc(dev); + + if (!netfront_tx_slot_available(np)) + netif_stop_queue(dev); + + spin_unlock_irq(&np->tx_lock); + + np->stats.tx_bytes += skb->len; + np->stats.tx_packets++; + + return 0; - if (unlikely(np->tx_full)) { - printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name); - netif_stop_queue(dev); - goto drop; - } + drop: + np->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; +} + +static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) +{ + struct net_device *dev = dev_id; + struct netfront_info *np = netdev_priv(dev); + unsigned long flags; - if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= - PAGE_SIZE)) { - struct sk_buff *nskb; - if (unlikely((nskb = alloc_xen_skb(skb->len)) == NULL)) - goto drop; - skb_put(nskb, skb->len); - memcpy(nskb->data, skb->data, skb->len); - nskb->dev = skb->dev; - dev_kfree_skb(skb); - skb = nskb; - } - - spin_lock_irq(&np->tx_lock); + spin_lock_irqsave(&np->tx_lock, flags); + network_tx_buf_gc(dev); + spin_unlock_irqrestore(&np->tx_lock, flags); - if (np->backend_state != BEST_CONNECTED) { - spin_unlock_irq(&np->tx_lock); - goto drop; - } + if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx) && + likely(netif_running(dev))) + netif_rx_schedule(dev); - i = np->tx->req_prod; + return IRQ_HANDLED; +} - id = GET_ID_FROM_FREELIST(np->tx_skbs); - np->tx_skbs[id] = skb; +static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb, + grant_ref_t ref) +{ + int new = xennet_rxidx(np->rx.req_prod_pvt); + + BUG_ON(np->rx_skbs[new]); + np->rx_skbs[new] = skb; + np->grant_rx_ref[new] = ref; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new; + RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref; + np->rx.req_prod_pvt++; +} - tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; +int xennet_get_extras(struct netfront_info *np, + struct netif_extra_info *extras, RING_IDX rp) - tx->id = id; - tx->addr = virt_to_machine(skb->data); - tx->size = skb->len; +{ + struct netif_extra_info *extra; + RING_IDX cons = np->rx.rsp_cons; + int err = 0; + + do { + struct sk_buff *skb; + grant_ref_t ref; + + if (unlikely(cons + 1 == rp)) { + if (net_ratelimit()) + WPRINTK("Missing extra info\n"); + err = -EBADR; + break; + } + + extra = (struct netif_extra_info *) + RING_GET_RESPONSE(&np->rx, ++cons); + + if (unlikely(!extra->type || + extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + if (net_ratelimit()) + WPRINTK("Invalid extra type: %d\n", + extra->type); + err = -EINVAL; + } else + memcpy(&extras[extra->type - 1], extra, sizeof(*extra)); + + skb = xennet_get_rx_skb(np, cons); + ref = xennet_get_rx_ref(np, cons); + xennet_move_rx_slot(np, skb, ref); + } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); + + np->rx.rsp_cons = cons; + return err; +} - wmb(); /* Ensure that backend will see the request. */ - np->tx->req_prod = i + 1; +static int xennet_get_responses(struct netfront_info *np, + struct netfront_rx_info *rinfo, RING_IDX rp, + struct sk_buff_head *list, int count) +{ + struct mmu_update *mmu = np->rx_mmu + count; + struct multicall_entry *mcl = np->rx_mcl + count; + struct netif_rx_response *rx = &rinfo->rx; + struct netif_extra_info *extras = rinfo->extras; + RING_IDX cons = np->rx.rsp_cons; + struct sk_buff *skb = xennet_get_rx_skb(np, cons); + grant_ref_t ref = xennet_get_rx_ref(np, cons); + int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD); + int frags = 1; + int err = 0; + + if (rx->flags & NETRXF_extra_info) { + err = xennet_get_extras(np, extras, rp); + cons = np->rx.rsp_cons; + } + + for (;;) { + unsigned long mfn; + + if (unlikely(rx->status < 0 || + rx->offset + rx->status > PAGE_SIZE)) { + if (net_ratelimit()) + WPRINTK("rx->offset: %x, size: %u\n", + rx->offset, rx->status); + err = -EINVAL; + } + + /* + * This definitely indicates a bug, either in this driver or in + * the backend driver. In future this should flag the bad + * situation to the system controller to reboot the backed. + */ + if (ref == GRANT_INVALID_REF) { + WPRINTK("Bad rx response id %d.\n", rx->id); + err = -EINVAL; + goto next; + } + + /* Memory pressure, insufficient buffer headroom, ... */ + if ((mfn = gnttab_end_foreign_transfer_ref(ref)) == 0) { + if (net_ratelimit()) + WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n", + rx->id, rx->status); + xennet_move_rx_slot(np, skb, ref); + err = -ENOMEM; + goto next; + } + + gnttab_release_grant_reference(&np->gref_rx_head, ref); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Remap the page. */ + struct page *page = skb_shinfo(skb)->frags[0].page; + unsigned long pfn = page_to_pfn(page); + void *vaddr = page_address(page); + + MULTI_update_va_mapping(mcl, (unsigned long)vaddr, + pfn_pte_ma(mfn, PAGE_KERNEL), + 0); + mcl++; + mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) + | MMU_MACHPHYS_UPDATE; + mmu->val = pfn; + mmu++; + + set_phys_to_machine(pfn, mfn); + } + + __skb_queue_tail(list, skb); + +next: + if (!(rx->flags & NETRXF_more_data)) + break; + + if (cons + frags == rp) { + if (net_ratelimit()) + WPRINTK("Need more frags\n"); + err = -ENOENT; + break; + } + + rx = RING_GET_RESPONSE(&np->rx, cons + frags); + skb = xennet_get_rx_skb(np, cons + frags); + ref = xennet_get_rx_ref(np, cons + frags); + frags++; + } + + if (unlikely(frags > max)) { + if (net_ratelimit()) + WPRINTK("Too many frags\n"); + err = -E2BIG; + } + + return err; +} - network_tx_buf_gc(dev); +static RING_IDX xennet_fill_frags(struct netfront_info *np, + struct sk_buff *skb, + struct sk_buff_head *list) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + RING_IDX cons = np->rx.rsp_cons; + skb_frag_t *frag = shinfo->frags + nr_frags; + struct sk_buff *nskb; - if ((i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1)) { - np->tx_full = 1; - netif_stop_queue(dev); - } + while ((nskb = __skb_dequeue(list))) { + struct netif_rx_response *rx = + RING_GET_RESPONSE(&np->rx, ++cons); - spin_unlock_irq(&np->tx_lock); + frag->page = skb_shinfo(nskb)->frags[0].page; + frag->page_offset = rx->offset; + frag->size = rx->status; - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; + skb->data_len += rx->status; - /* Only notify Xen if we really have to. */ - mb(); - if (np->tx->TX_TEST_IDX == i) - notify_via_evtchn(np->evtchn); + skb_shinfo(nskb)->nr_frags = 0; + kfree_skb(nskb); - return 0; + frag++; + nr_frags++; + } - drop: - np->stats.tx_dropped++; - dev_kfree_skb(skb); - return 0; + shinfo->nr_frags = nr_frags; + return cons; } -static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) +static int xennet_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso) { - struct net_device *dev = dev_id; - struct net_private *np = netdev_priv(dev); - unsigned long flags; + if (!gso->u.gso.size) { + if (net_ratelimit()) + WPRINTK("GSO size must not be zero.\n"); + return -EINVAL; + } + + /* Currently only TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { + if (net_ratelimit()) + WPRINTK("Bad GSO type %d.\n", gso->u.gso.type); + return -EINVAL; + } + + skb_shinfo(skb)->gso_size = gso->u.gso.size; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + + return 0; +} - spin_lock_irqsave(&np->tx_lock, flags); - network_tx_buf_gc(dev); - spin_unlock_irqrestore(&np->tx_lock, flags); +static int netif_poll(struct net_device *dev, int *pbudget) +{ + struct netfront_info *np = netdev_priv(dev); + struct sk_buff *skb; + struct netfront_rx_info rinfo; + struct netif_rx_response *rx = &rinfo.rx; + struct netif_extra_info *extras = rinfo.extras; + RING_IDX i, rp; + struct multicall_entry *mcl; + int work_done, budget, more_to_do = 1; + struct sk_buff_head rxq; + struct sk_buff_head errq; + struct sk_buff_head tmpq; + unsigned long flags; + unsigned int len; + int pages_done; + int err; + + spin_lock(&np->rx_lock); + + if (unlikely(!netif_carrier_ok(dev))) { + spin_unlock(&np->rx_lock); + return 0; + } + + skb_queue_head_init(&rxq); + skb_queue_head_init(&errq); + skb_queue_head_init(&tmpq); + + if ((budget = *pbudget) > dev->quota) + budget = dev->quota; + rp = np->rx.sring->rsp_prod; + rmb(); /* Ensure we see queued responses up to 'rp'. */ + + for (i = np->rx.rsp_cons, work_done = 0, pages_done = 0; + (i != rp) && (work_done < budget); + np->rx.rsp_cons = ++i, work_done++) { + memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx)); + memset(extras, 0, sizeof(extras)); + + err = xennet_get_responses(np, &rinfo, rp, &tmpq, pages_done); + pages_done += skb_queue_len(&tmpq); + + if (unlikely(err)) { +err: + i = np->rx.rsp_cons + skb_queue_len(&tmpq) - 1; + work_done--; + while ((skb = __skb_dequeue(&tmpq))) + __skb_queue_tail(&errq, skb); + np->stats.rx_errors++; + continue; + } + + skb = __skb_dequeue(&tmpq); + + if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) { + struct netif_extra_info *gso; + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + if (unlikely(xennet_set_skb_gso(skb, gso))) { + __skb_queue_head(&tmpq, skb); + goto err; + } + } + + skb->nh.raw = (void *)skb_shinfo(skb)->frags[0].page; + skb->h.raw = skb->nh.raw + rx->offset; + + len = rx->status; + if (len > RX_COPY_THRESHOLD) + len = RX_COPY_THRESHOLD; + skb_put(skb, len); + + if (rx->status > len) { + skb_shinfo(skb)->frags[0].page_offset = + rx->offset + len; + skb_shinfo(skb)->frags[0].size = rx->status - len; + skb->data_len = rx->status - len; + } else { + skb_shinfo(skb)->frags[0].page = NULL; + skb_shinfo(skb)->nr_frags = 0; + } + + i = xennet_fill_frags(np, skb, &tmpq); + skb->truesize += skb->data_len; + skb->len += skb->data_len; + + /* + * Old backends do not assert data_validated but we + * can infer it from csum_blank so test both flags. + */ + if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->proto_data_valid = 1; + } else { + skb->ip_summed = CHECKSUM_NONE; + skb->proto_data_valid = 0; + } + skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank); + + np->stats.rx_packets++; + np->stats.rx_bytes += skb->len; + + __skb_queue_tail(&rxq, skb); + } + + /* Some pages are no longer absent... */ + balloon_update_driver_allowance(-pages_done); + + /* Do all the remapping work, and M2P updates, in one big hypercall. */ + if (likely(pages_done)) { + mcl = np->rx_mcl + pages_done; + mcl->op = __HYPERVISOR_mmu_update; + mcl->args[0] = (unsigned long)np->rx_mmu; + mcl->args[1] = pages_done; + mcl->args[2] = 0; + mcl->args[3] = DOMID_SELF; + (void)HYPERVISOR_multicall(np->rx_mcl, pages_done + 1); + } + + while ((skb = __skb_dequeue(&errq))) + kfree_skb(skb); + + while ((skb = __skb_dequeue(&rxq)) != NULL) { + struct page *page = (struct page *)skb->nh.raw; + void *vaddr = page_address(page); + + memcpy(skb->data, vaddr + (skb->h.raw - skb->nh.raw), + skb_headlen(skb)); + + if (page != skb_shinfo(skb)->frags[0].page) + __free_page(page); + + /* Ethernet work: Delayed to here as it peeks the header. */ + skb->protocol = eth_type_trans(skb, dev); + + /* Pass it up. */ + netif_receive_skb(skb); + dev->last_rx = jiffies; + } + + /* If we get a callback with very few responses, reduce fill target. */ + /* NB. Note exponential increase, linear decrease. */ + if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) > + ((3*np->rx_target) / 4)) && + (--np->rx_target < np->rx_min_target)) + np->rx_target = np->rx_min_target; + + network_alloc_rx_buffers(dev); + + *pbudget -= work_done; + dev->quota -= work_done; + + if (work_done < budget) { + local_irq_save(flags); + + RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do); + if (!more_to_do) + __netif_rx_complete(dev); + + local_irq_restore(flags); + } + + spin_unlock(&np->rx_lock); + + return more_to_do; +} - if ((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN)) - netif_rx_schedule(dev); - return IRQ_HANDLED; +static int network_close(struct net_device *dev) +{ + struct netfront_info *np = netdev_priv(dev); + netif_stop_queue(np->netdev); + return 0; } -static int netif_poll(struct net_device *dev, int *pbudget) +static struct net_device_stats *network_get_stats(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); - struct sk_buff *skb, *nskb; - netif_rx_response_t *rx; - NETIF_RING_IDX i, rp; - mmu_update_t *mmu = rx_mmu; - multicall_entry_t *mcl = rx_mcl; - int work_done, budget, more_to_do = 1; - struct sk_buff_head rxq; - unsigned long flags; - - spin_lock(&np->rx_lock); - - if (np->backend_state != BEST_CONNECTED) { - spin_unlock(&np->rx_lock); - return 0; - } - - skb_queue_head_init(&rxq); - - if ((budget = *pbudget) > dev->quota) - budget = dev->quota; - - rp = np->rx->resp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ - - for (i = np->rx_resp_cons, work_done = 0; - (i != rp) && (work_done < budget); - i++, work_done++) { - rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; - - /* - * An error here is very odd. Usually indicates a backend bug, - * low-memory condition, or that we didn't have reservation headroom. - */ - if (unlikely(rx->status <= 0)) { - if (net_ratelimit()) - printk(KERN_WARNING "Bad rx buffer (memory squeeze?).\n"); - np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; - wmb(); - np->rx->req_prod++; - work_done--; - continue; - } - - skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); - - /* NB. We handle skb overflow later. */ - skb->data = skb->head + (rx->addr & ~PAGE_MASK); - skb->len = rx->status; - skb->tail = skb->data + skb->len; - - np->stats.rx_packets++; - np->stats.rx_bytes += rx->status; - - /* Remap the page. */ - mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; - mmu->val = __pa(skb->head) >> PAGE_SHIFT; - mmu++; - mcl->op = __HYPERVISOR_update_va_mapping; - mcl->args[0] = (unsigned long)skb->head; - mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL; - mcl->args[2] = 0; - mcl++; - - phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = - rx->addr >> PAGE_SHIFT; - - __skb_queue_tail(&rxq, skb); - } - - /* Some pages are no longer absent... */ - balloon_update_driver_allowance(-work_done); - - /* Do all the remapping work, and M->P updates, in one big hypercall. */ - if (likely((mcl - rx_mcl) != 0)) { - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; - mcl->args[2] = 0; - mcl->args[3] = DOMID_SELF; - mcl++; - (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); - } - - while ((skb = __skb_dequeue(&rxq)) != NULL) { - /* - * Enough room in skbuff for the data we were passed? Also, Linux - * expects at least 16 bytes headroom in each receive buffer. - */ - if (unlikely(skb->tail > skb->end) || - unlikely((skb->data - skb->head) < 16)) { - nskb = NULL; - - /* Only copy the packet if it fits in the current MTU. */ - if (skb->len <= (dev->mtu + ETH_HLEN)) { - if ((skb->tail > skb->end) && net_ratelimit()) - printk(KERN_INFO "Received packet needs %d bytes more " - "headroom.\n", skb->tail - skb->end); - - if ((nskb = alloc_xen_skb(skb->len + 2)) != NULL) { - skb_reserve(nskb, 2); - skb_put(nskb, skb->len); - memcpy(nskb->data, skb->data, skb->len); - nskb->dev = skb->dev; - } - } - else if (net_ratelimit()) - printk(KERN_INFO "Received packet too big for MTU " - "(%d > %d)\n", skb->len - ETH_HLEN, dev->mtu); - - /* Reinitialise and then destroy the old skbuff. */ - skb->len = 0; - skb->tail = skb->data; - init_skb_shinfo(skb); - dev_kfree_skb(skb); - - /* Switch old for new, if we copied the buffer. */ - if ((skb = nskb) == NULL) - continue; - } - - /* Set the shared-info area, which is hidden behind the real data. */ - init_skb_shinfo(skb); - - /* Ethernet-specific work. Delayed to here as it peeks the header. */ - skb->protocol = eth_type_trans(skb, dev); - - /* Pass it up. */ - netif_receive_skb(skb); - dev->last_rx = jiffies; - } - - np->rx_resp_cons = i; - - /* If we get a callback with very few responses, reduce fill target. */ - /* NB. Note exponential increase, linear decrease. */ - if (((np->rx->req_prod - np->rx->resp_prod) > ((3*np->rx_target) / 4)) && - (--np->rx_target < RX_MIN_TARGET)) - np->rx_target = RX_MIN_TARGET; - - network_alloc_rx_buffers(dev); - - *pbudget -= work_done; - dev->quota -= work_done; - - if (work_done < budget) { - local_irq_save(flags); - - np->rx->event = i + 1; - - /* Deal with hypervisor racing our resetting of rx_event. */ - mb(); - if (np->rx->resp_prod == i) { - __netif_rx_complete(dev); - more_to_do = 0; - } - - local_irq_restore(flags); - } - - spin_unlock(&np->rx_lock); - - return more_to_do; + struct netfront_info *np = netdev_priv(dev); + return &np->stats; } +static int xennet_change_mtu(struct net_device *dev, int mtu) +{ + int max = xennet_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN; -static int network_close(struct net_device *dev) + if (mtu > max) + return -EINVAL; + dev->mtu = mtu; + return 0; +} + +static int xennet_set_sg(struct net_device *dev, u32 data) { - struct net_private *np = netdev_priv(dev); - np->user_state = UST_CLOSED; - netif_stop_queue(np->dev); - return 0; + if (data) { + struct netfront_info *np = netdev_priv(dev); + int val; + + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", + "%d", &val) < 0) + val = 0; + if (!val) + return -ENOSYS; + } else if (dev->mtu > ETH_DATA_LEN) + dev->mtu = ETH_DATA_LEN; + + return ethtool_op_set_sg(dev, data); } +static int xennet_set_tso(struct net_device *dev, u32 data) +{ + if (data) { + struct netfront_info *np = netdev_priv(dev); + int val; + + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, + "feature-gso-tcpv4", "%d", &val) < 0) + val = 0; + if (!val) + return -ENOSYS; + } + + return ethtool_op_set_tso(dev, data); +} -static struct net_device_stats *network_get_stats(struct net_device *dev) +static void xennet_set_features(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); - return &np->stats; + /* Turn off all GSO bits except ROBUST. */ + dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1; + dev->features |= NETIF_F_GSO_ROBUST; + xennet_set_sg(dev, 0); + + if (!xennet_set_sg(dev, 1)) + xennet_set_tso(dev, 1); } +static void network_connect(struct net_device *dev) +{ + struct netfront_info *np = netdev_priv(dev); + int i, requeue_idx; + struct sk_buff *skb; + grant_ref_t ref; + + xennet_set_features(dev); + + spin_lock_irq(&np->tx_lock); + spin_lock(&np->rx_lock); + + /* + * Recovery procedure: + * NB. Freelist index entries are always going to be less than + * PAGE_OFFSET, whereas pointers to skbs will always be equal or + * greater than PAGE_OFFSET: we use this property to distinguish + * them. + */ + + /* Step 1: Discard all pending TX packet fragments. */ + for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) { + if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET) + continue; + + skb = np->tx_skbs[i]; + gnttab_end_foreign_access_ref( + np->grant_tx_ref[i], GNTMAP_readonly); + gnttab_release_grant_reference( + &np->gref_tx_head, np->grant_tx_ref[i]); + np->grant_tx_ref[i] = GRANT_INVALID_REF; + add_id_to_freelist(np->tx_skbs, i); + dev_kfree_skb_irq(skb); + } + + /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */ + for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) { + if (!np->rx_skbs[i]) + continue; + + skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i); + ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i); + + gnttab_grant_foreign_transfer_ref( + ref, np->xbdev->otherend_id, + page_to_pfn(skb_shinfo(skb)->frags->page)); + + RING_GET_REQUEST(&np->rx, requeue_idx)->gref = ref; + RING_GET_REQUEST(&np->rx, requeue_idx)->id = requeue_idx; + + requeue_idx++; + } + + np->rx.req_prod_pvt = requeue_idx; + + /* + * Step 3: All public and private state should now be sane. Get + * ready to start sending and receiving packets and give the driver + * domain a kick because we've probably just requeued some + * packets. + */ + netif_carrier_on(dev); + notify_remote_via_irq(np->irq); + network_tx_buf_gc(dev); + network_alloc_rx_buffers(dev); + + spin_unlock(&np->rx_lock); + spin_unlock_irq(&np->tx_lock); +} -static void network_connect(struct net_device *dev, - netif_fe_interface_status_t *status) +static void netif_uninit(struct net_device *dev) { - struct net_private *np; - int i, requeue_idx; - netif_tx_request_t *tx; - - np = netdev_priv(dev); - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); - - /* Recovery procedure: */ - - /* Step 1: Reinitialise variables. */ - np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; - np->rx->event = np->tx->event = 1; - - /* Step 2: Rebuild the RX and TX ring contents. - * NB. We could just free the queued TX packets now but we hope - * that sending them out might do some good. We have to rebuild - * the RX ring because some of our pages are currently flipped out - * so we can't just free the RX skbs. - * NB2. Freelist index entries are always going to be less than - * __PAGE_OFFSET, whereas pointers to skbs will always be equal or - * greater than __PAGE_OFFSET: we use this property to distinguish - * them. - */ - - /* Rebuild the TX buffer freelist and the TX ring itself. - * NB. This reorders packets. We could keep more private state - * to avoid this but maybe it doesn't matter so much given the - * interface has been down. - */ - for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) { - if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) { - struct sk_buff *skb = np->tx_skbs[i]; - - tx = &np->tx->ring[requeue_idx++].req; - - tx->id = i; - tx->addr = virt_to_machine(skb->data); - tx->size = skb->len; - - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - } - } - wmb(); - np->tx->req_prod = requeue_idx; - - /* Rebuild the RX buffer freelist and the RX ring itself. */ - for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) - if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) - np->rx->ring[requeue_idx++].req.id = i; - wmb(); - np->rx->req_prod = requeue_idx; - - /* Step 3: All public and private state should now be sane. Get - * ready to start sending and receiving packets and give the driver - * domain a kick because we've probably just requeued some - * packets. - */ - np->backend_state = BEST_CONNECTED; - wmb(); - notify_via_evtchn(status->evtchn); - network_tx_buf_gc(dev); - - if (np->user_state == UST_OPEN) - netif_start_queue(dev); - - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); + struct netfront_info *np = netdev_priv(dev); + gnttab_free_grant_references(np->gref_tx_head); + gnttab_free_grant_references(np->gref_rx_head); } -static void vif_show(struct net_private *np) +static struct ethtool_ops network_ethtool_ops = { -#if DEBUG - if (np) { - IPRINTK("\n", - np->handle, - be_state_name[np->backend_state], - np->user_state ? "open" : "closed", - np->evtchn, - np->irq, - np->tx, - np->rx); - } else { - IPRINTK("\n"); - } -#endif + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = xennet_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = xennet_set_tso, + .get_link = ethtool_op_get_link, +}; + +#ifdef CONFIG_SYSFS +static ssize_t show_rxbuf_min(struct class_device *cd, char *buf) +{ + struct net_device *netdev = container_of(cd, struct net_device, + class_dev); + struct netfront_info *info = netdev_priv(netdev); + + return sprintf(buf, "%u\n", info->rx_min_target); } -/* Send a connect message to xend to tell it to bring up the interface. */ -static void send_interface_connect(struct net_private *np) +static ssize_t store_rxbuf_min(struct class_device *cd, + const char *buf, size_t len) { - ctrl_msg_t cmsg = { - .type = CMSG_NETIF_FE, - .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT, - .length = sizeof(netif_fe_interface_connect_t), - }; - netif_fe_interface_connect_t *msg = (void*)cmsg.msg; - - msg->handle = np->handle; - msg->tx_shmem_frame = (virt_to_machine(np->tx) >> PAGE_SHIFT); - msg->rx_shmem_frame = (virt_to_machine(np->rx) >> PAGE_SHIFT); - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); + struct net_device *netdev = container_of(cd, struct net_device, + class_dev); + struct netfront_info *np = netdev_priv(netdev); + char *endp; + unsigned long target; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + target = simple_strtoul(buf, &endp, 0); + if (endp == buf) + return -EBADMSG; + + if (target < RX_MIN_TARGET) + target = RX_MIN_TARGET; + if (target > RX_MAX_TARGET) + target = RX_MAX_TARGET; + + spin_lock(&np->rx_lock); + if (target > np->rx_max_target) + np->rx_max_target = target; + np->rx_min_target = target; + if (target > np->rx_target) + np->rx_target = target; + + network_alloc_rx_buffers(netdev); + + spin_unlock(&np->rx_lock); + return len; } -/* Send a driver status notification to the domain controller. */ -static int send_driver_status(int ok) +static ssize_t show_rxbuf_max(struct class_device *cd, char *buf) { - int err = 0; - ctrl_msg_t cmsg = { - .type = CMSG_NETIF_FE, - .subtype = CMSG_NETIF_FE_DRIVER_STATUS, - .length = sizeof(netif_fe_driver_status_t), - }; - netif_fe_driver_status_t *msg = (void*)cmsg.msg; - - msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN); - err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - return err; + struct net_device *netdev = container_of(cd, struct net_device, + class_dev); + struct netfront_info *info = netdev_priv(netdev); + + return sprintf(buf, "%u\n", info->rx_max_target); } -/* Stop network device and free tx/rx queues and irq. - */ -static void vif_release(struct net_private *np) +static ssize_t store_rxbuf_max(struct class_device *cd, + const char *buf, size_t len) { - /* Stop old i/f to prevent errors whilst we rebuild the state. */ - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); - netif_stop_queue(np->dev); - /* np->backend_state = BEST_DISCONNECTED; */ - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); - - /* Free resources. */ - if(np->tx != NULL){ - free_irq(np->irq, np->dev); - unbind_evtchn_from_irq(np->evtchn); - free_page((unsigned long)np->tx); - free_page((unsigned long)np->rx); - np->irq = 0; - np->evtchn = 0; - np->tx = NULL; - np->rx = NULL; - } + struct net_device *netdev = container_of(cd, struct net_device, + class_dev); + struct netfront_info *np = netdev_priv(netdev); + char *endp; + unsigned long target; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + target = simple_strtoul(buf, &endp, 0); + if (endp == buf) + return -EBADMSG; + + if (target < RX_MIN_TARGET) + target = RX_MIN_TARGET; + if (target > RX_MAX_TARGET) + target = RX_MAX_TARGET; + + spin_lock(&np->rx_lock); + if (target < np->rx_min_target) + np->rx_min_target = target; + np->rx_max_target = target; + if (target < np->rx_target) + np->rx_target = target; + + network_alloc_rx_buffers(netdev); + + spin_unlock(&np->rx_lock); + return len; } -/* Release vif resources and close it down completely. - */ -static void vif_close(struct net_private *np) +static ssize_t show_rxbuf_cur(struct class_device *cd, char *buf) { - WPRINTK("Unexpected netif-CLOSED message in state %s\n", - be_state_name[np->backend_state]); - vif_release(np); - np->backend_state = BEST_CLOSED; - /* todo: take dev down and free. */ - vif_show(np); + struct net_device *netdev = container_of(cd, struct net_device, + class_dev); + struct netfront_info *info = netdev_priv(netdev); + + return sprintf(buf, "%u\n", info->rx_target); } -/* Move the vif into disconnected state. - * Allocates tx/rx pages. - * Sends connect message to xend. - */ -static void vif_disconnect(struct net_private *np) +static const struct class_device_attribute xennet_attrs[] = { + __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min), + __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max), + __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL), +}; + +static int xennet_sysfs_addif(struct net_device *netdev) { - if(np->tx) free_page((unsigned long)np->tx); - if(np->rx) free_page((unsigned long)np->rx); - // Before this np->tx and np->rx had better be null. - np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); - np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); - memset(np->tx, 0, PAGE_SIZE); - memset(np->rx, 0, PAGE_SIZE); - np->backend_state = BEST_DISCONNECTED; - send_interface_connect(np); - vif_show(np); + int i; + int error = 0; + + for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) { + error = class_device_create_file(&netdev->class_dev, + &xennet_attrs[i]); + if (error) + goto fail; + } + return 0; + + fail: + while (--i >= 0) + class_device_remove_file(&netdev->class_dev, + &xennet_attrs[i]); + return error; } -/* Begin interface recovery. - * - * NB. Whilst we're recovering, we turn the carrier state off. We - * take measures to ensure that this device isn't used for - * anything. We also stop the queue for this device. Various - * different approaches (e.g. continuing to buffer packets) have - * been tested but don't appear to improve the overall impact on - * TCP connections. - * - * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery - * is initiated by a special "RESET" message - disconnect could - * just mean we're not allowed to use this interface any more. - */ -static void vif_reset(struct net_private *np) +static void xennet_sysfs_delif(struct net_device *netdev) { - IPRINTK("Attempting to reconnect network interface: handle=%u\n", - np->handle); - vif_release(np); - vif_disconnect(np); - vif_show(np); + int i; + + for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) { + class_device_remove_file(&netdev->class_dev, + &xennet_attrs[i]); + } } -/* Move the vif into connected state. - * Sets the mac and event channel from the message. - * Binds the irq to the event channel. +#endif /* CONFIG_SYSFS */ + + +/* + * Nothing to do here. Virtual interface is point-to-point and the + * physical interface is probably promiscuous anyway. */ -static void -vif_connect(struct net_private *np, netif_fe_interface_status_t *status) +static void network_set_multicast_list(struct net_device *dev) { - struct net_device *dev = np->dev; - memcpy(dev->dev_addr, status->mac, ETH_ALEN); - network_connect(dev, status); - np->evtchn = status->evtchn; - np->irq = bind_evtchn_to_irq(np->evtchn); - (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); - netctrl_connected_count(); - (void)send_fake_arp(dev); - vif_show(np); } - /** Create a network device. * @param handle device handle * @param val return parameter for created device * @return 0 on success, error code otherwise */ -static int create_netdev(int handle, struct net_device **val) +static struct net_device * __devinit create_netdev(int handle, + struct xenbus_device *dev) { - int i, err = 0; - struct net_device *dev = NULL; - struct net_private *np = NULL; - - if ((dev = alloc_etherdev(sizeof(struct net_private))) == NULL) { - printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__); - err = -ENOMEM; - goto exit; - } - - np = netdev_priv(dev); - np->backend_state = BEST_CLOSED; - np->user_state = UST_CLOSED; - np->handle = handle; - - spin_lock_init(&np->tx_lock); - spin_lock_init(&np->rx_lock); - - skb_queue_head_init(&np->rx_batch); - np->rx_target = RX_MIN_TARGET; - - /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ - for (i = 0; i <= NETIF_TX_RING_SIZE; i++) - np->tx_skbs[i] = (void *)(i+1); - for (i = 0; i <= NETIF_RX_RING_SIZE; i++) - np->rx_skbs[i] = (void *)(i+1); - - dev->open = network_open; - dev->hard_start_xmit = network_start_xmit; - dev->stop = network_close; - dev->get_stats = network_get_stats; - dev->poll = netif_poll; - dev->weight = 64; - - if ((err = register_netdev(dev)) != 0) { - printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err); - goto exit; - } - np->dev = dev; - list_add(&np->list, &dev_list); - - exit: - if ((err != 0) && (dev != NULL )) - kfree(dev); - else if (val != NULL) - *val = dev; - return err; + int i, err = 0; + struct net_device *netdev = NULL; + struct netfront_info *np = NULL; + + netdev = alloc_etherdev(sizeof(struct netfront_info)); + if (!netdev) { + printk(KERN_WARNING "%s> alloc_etherdev failed.\n", + __FUNCTION__); + return ERR_PTR(-ENOMEM); + } + + np = netdev_priv(netdev); + np->handle = handle; + np->xbdev = dev; + + netif_carrier_off(netdev); + + spin_lock_init(&np->tx_lock); + spin_lock_init(&np->rx_lock); + + skb_queue_head_init(&np->rx_batch); + np->rx_target = RX_DFL_MIN_TARGET; + np->rx_min_target = RX_DFL_MIN_TARGET; + np->rx_max_target = RX_MAX_TARGET; + + init_timer(&np->rx_refill_timer); + np->rx_refill_timer.data = (unsigned long)netdev; + np->rx_refill_timer.function = rx_refill_timeout; + + /* Initialise {tx,rx}_skbs as a free chain containing every entry. */ + for (i = 0; i <= NET_TX_RING_SIZE; i++) { + np->tx_skbs[i] = (void *)((unsigned long) i+1); + np->grant_tx_ref[i] = GRANT_INVALID_REF; + } + + for (i = 0; i < NET_RX_RING_SIZE; i++) { + np->rx_skbs[i] = NULL; + np->grant_rx_ref[i] = GRANT_INVALID_REF; + } + + /* A grant for every tx ring slot */ + if (gnttab_alloc_grant_references(TX_MAX_TARGET, + &np->gref_tx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); + err = -ENOMEM; + goto exit; + } + /* A grant for every rx ring slot */ + if (gnttab_alloc_grant_references(RX_MAX_TARGET, + &np->gref_rx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); + err = -ENOMEM; + goto exit_free_tx; + } + + netdev->open = network_open; + netdev->hard_start_xmit = network_start_xmit; + netdev->stop = network_close; + netdev->get_stats = network_get_stats; + netdev->poll = netif_poll; + netdev->set_multicast_list = network_set_multicast_list; + netdev->uninit = netif_uninit; + netdev->change_mtu = xennet_change_mtu; + netdev->weight = 64; + netdev->features = NETIF_F_IP_CSUM; + + SET_ETHTOOL_OPS(netdev, &network_ethtool_ops); + SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &dev->dev); + + err = register_netdev(netdev); + if (err) { + printk(KERN_WARNING "%s> register_netdev err=%d\n", + __FUNCTION__, err); + goto exit_free_rx; + } + + err = xennet_sysfs_addif(netdev); + if (err) { + /* This can be non-fatal: it only means no tuning parameters */ + printk(KERN_WARNING "%s> add sysfs failed err=%d\n", + __FUNCTION__, err); + } + + np->netdev = netdev; + + return netdev; + + + exit_free_rx: + gnttab_free_grant_references(np->gref_rx_head); + exit_free_tx: + gnttab_free_grant_references(np->gref_tx_head); + exit: + free_netdev(netdev); + return ERR_PTR(err); } -/* Get the target interface for a status message. - * Creates the interface when it makes sense. - * The returned interface may be null when there is no error. - * - * @param status status message - * @param np return parameter for interface state - * @return 0 on success, error code otherwise +/* + * We use this notifier to send out a fake ARP reply to reset switches and + * router ARP caches when an IP interface is brought up on a VIF. */ -static int -target_vif(netif_fe_interface_status_t *status, struct net_private **np) +static int +inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr) { - int err = 0; - struct net_device *dev; - - DPRINTK("> handle=%d\n", status->handle); - if (status->handle < 0) { - err = -EINVAL; - goto exit; - } - - if ((dev = find_dev_by_handle(status->handle)) != NULL) - goto exit; - - if (status->status == NETIF_INTERFACE_STATUS_CLOSED) - goto exit; - if (status->status == NETIF_INTERFACE_STATUS_CHANGED) - goto exit; - - /* It's a new interface in a good state - create it. */ - DPRINTK("> create device...\n"); - if ((err = create_netdev(status->handle, &dev)) != 0) - goto exit; - - netctrl.interface_n++; - - exit: - if (np != NULL) - *np = ((dev && !err) ? netdev_priv(dev) : NULL); - DPRINTK("< err=%d\n", err); - return err; + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *dev = ifa->ifa_dev->dev; + + /* UP event and is it one of our devices? */ + if (event == NETDEV_UP && dev->open == network_open) + (void)send_fake_arp(dev); + + return NOTIFY_DONE; } -/* Handle an interface status message. */ -static void netif_interface_status(netif_fe_interface_status_t *status) -{ - int err = 0; - struct net_private *np = NULL; - - DPRINTK("> status=%s handle=%d\n", - status_name[status->status], status->handle); - - if ((err = target_vif(status, &np)) != 0) { - WPRINTK("Invalid netif: handle=%u\n", status->handle); - return; - } - - if (np == NULL) { - DPRINTK("> no vif\n"); - return; - } - - switch (status->status) { - case NETIF_INTERFACE_STATUS_CLOSED: - switch (np->backend_state) { - case BEST_CLOSED: - case BEST_DISCONNECTED: - case BEST_CONNECTED: - vif_close(np); - break; - } - break; - - case NETIF_INTERFACE_STATUS_DISCONNECTED: - switch (np->backend_state) { - case BEST_CLOSED: - vif_disconnect(np); - break; - case BEST_DISCONNECTED: - case BEST_CONNECTED: - vif_reset(np); - break; - } - break; - - case NETIF_INTERFACE_STATUS_CONNECTED: - switch (np->backend_state) { - case BEST_CLOSED: - WPRINTK("Unexpected netif status %s in state %s\n", - status_name[status->status], - be_state_name[np->backend_state]); - vif_disconnect(np); - vif_connect(np, status); - break; - case BEST_DISCONNECTED: - vif_connect(np, status); - break; - } - break; - - case NETIF_INTERFACE_STATUS_CHANGED: - /* - * The domain controller is notifying us that a device has been - * added or removed. - */ - break; - default: - WPRINTK("Invalid netif status code %d\n", status->status); - break; - } +/* ** Close down ** */ - vif_show(np); -} -/* - * Initialize the network control interface. +/** + * Handle the change of state of the backend to Closing. We must delete our + * device-layer structures now, to ensure that writes are flushed through to + * the backend. Once is this done, we can switch to Closed in + * acknowledgement. */ -static void netif_driver_status(netif_fe_driver_status_t *status) +static void netfront_closing(struct xenbus_device *dev) { - netctrl.up = status->status; - netctrl_connected_count(); + struct netfront_info *info = dev->dev.driver_data; + + DPRINTK("netfront_closing: %s removed\n", dev->nodename); + + close_netdev(info); + + xenbus_switch_state(dev, XenbusStateClosed); } -/* Receive handler for control messages. */ -static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - switch (msg->subtype) { - case CMSG_NETIF_FE_INTERFACE_STATUS: - netif_interface_status((netif_fe_interface_status_t *) &msg->msg[0]); - break; +static int __devexit netfront_remove(struct xenbus_device *dev) +{ + struct netfront_info *info = dev->dev.driver_data; - case CMSG_NETIF_FE_DRIVER_STATUS: - netif_driver_status((netif_fe_driver_status_t *) &msg->msg[0]); - break; + DPRINTK("%s\n", dev->nodename); - default: - msg->length = 0; - break; - } + netif_disconnect_backend(info); + free_netdev(info->netdev); - ctrl_if_send_response(msg); + return 0; } -#if 1 -/* Wait for all interfaces to be connected. - * - * This works OK, but we'd like to use the probing mode (see below). - */ -static int probe_interfaces(void) +static void close_netdev(struct netfront_info *info) { - int err = 0, conn = 0; - int wait_i, wait_n = 100; + del_timer_sync(&info->rx_refill_timer); - DPRINTK(">\n"); + xennet_sysfs_delif(info->netdev); + unregister_netdev(info->netdev); +} - for (wait_i = 0; wait_i < wait_n; wait_i++) { - DPRINTK("> wait_i=%d\n", wait_i); - conn = netctrl_connected(); - if(conn) break; - DPRINTK("> schedule_timeout...\n"); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); - } - DPRINTK("> wait finished...\n"); - if (conn <= 0) { - err = netctrl_err(-ENETDOWN); - WPRINTK("Failed to connect all virtual interfaces: err=%d\n", err); - } +static void netif_disconnect_backend(struct netfront_info *info) +{ + /* Stop old i/f to prevent errors whilst we rebuild the state. */ + spin_lock_irq(&info->tx_lock); + spin_lock(&info->rx_lock); + netif_carrier_off(info->netdev); + spin_unlock(&info->rx_lock); + spin_unlock_irq(&info->tx_lock); + + if (info->irq) + unbind_from_irqhandler(info->irq, info->netdev); + info->evtchn = info->irq = 0; + + end_access(info->tx_ring_ref, info->tx.sring); + end_access(info->rx_ring_ref, info->rx.sring); + info->tx_ring_ref = GRANT_INVALID_REF; + info->rx_ring_ref = GRANT_INVALID_REF; + info->tx.sring = NULL; + info->rx.sring = NULL; +} - DPRINTK("< err=%d\n", err); - return err; -} -#else -/* Probe for interfaces until no more are found. - * - * This is the mode we'd like to use, but at the moment it panics the kernel. -*/ -static int probe_interfaces(void) +static void netif_free(struct netfront_info *info) { - int err = 0; - int wait_i, wait_n = 100; - ctrl_msg_t cmsg = { - .type = CMSG_NETIF_FE, - .subtype = CMSG_NETIF_FE_INTERFACE_STATUS, - .length = sizeof(netif_fe_interface_status_t), - }; - netif_fe_interface_status_t msg = {}; - ctrl_msg_t rmsg = {}; - netif_fe_interface_status_t *reply = (void*)rmsg.msg; - int state = TASK_UNINTERRUPTIBLE; - u32 query = -1; - - DPRINTK(">\n"); - - netctrl.interface_n = 0; - for (wait_i = 0; wait_i < wait_n; wait_i++) { - DPRINTK("> wait_i=%d query=%d\n", wait_i, query); - msg.handle = query; - memcpy(cmsg.msg, &msg, sizeof(msg)); - DPRINTK("> set_current_state...\n"); - set_current_state(state); - DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply); - DPRINTK("> sending...\n"); - err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state); - DPRINTK("> err=%d\n", err); - if(err) goto exit; - DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply); - if((int)reply->handle < 0) { - // No more interfaces. - break; - } - query = -reply->handle - 2; - DPRINTK(">netif_interface_status ...\n"); - netif_interface_status(reply); - } - - exit: - if (err) { - err = netctrl_err(-ENETDOWN); - WPRINTK("Connecting virtual network interfaces failed: err=%d\n", err); - } - - DPRINTK("< err=%d\n", err); - return err; + close_netdev(info); + netif_disconnect_backend(info); + free_netdev(info->netdev); } -#endif -/* - * We use this notifier to send out a fake ARP reply to reset switches and - * router ARP caches when an IP interface is brought up on a VIF. - */ -static int -inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr) +static void end_access(int ref, void *page) { - struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; - struct net_device *dev = ifa->ifa_dev->dev; - struct list_head *ent; - struct net_private *np; - - if (event != NETDEV_UP) - goto out; - - list_for_each (ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - if (np->dev == dev) - (void)send_fake_arp(dev); - } - - out: - return NOTIFY_DONE; + if (ref != GRANT_INVALID_REF) + gnttab_end_foreign_access(ref, 0, (unsigned long)page); } + +/* ** Driver registration ** */ + + +static struct xenbus_device_id netfront_ids[] = { + { "vif" }, + { "" } +}; + + +static struct xenbus_driver netfront = { + .name = "vif", + .owner = THIS_MODULE, + .ids = netfront_ids, + .probe = netfront_probe, + .remove = __devexit_p(netfront_remove), + .resume = netfront_resume, + .otherend_changed = backend_changed, +}; + + static struct notifier_block notifier_inetdev = { - .notifier_call = inetdev_notify, - .next = NULL, - .priority = 0 + .notifier_call = inetdev_notify, + .next = NULL, + .priority = 0 }; static int __init netif_init(void) { - int err = 0; - - if (xen_start_info.flags & SIF_INITDOMAIN) - return 0; - - IPRINTK("Initialising virtual ethernet driver.\n"); - INIT_LIST_HEAD(&dev_list); - (void)register_inetaddr_notifier(¬ifier_inetdev); - netctrl_init(); - (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); - send_driver_status(1); - err = probe_interfaces(); - if (err) - ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx); - - DPRINTK("< err=%d\n", err); - return err; -} + if (!is_running_on_xen()) + return -ENODEV; -static void vif_suspend(struct net_private *np) -{ - /* Avoid having tx/rx stuff happen until we're ready. */ - free_irq(np->irq, np->dev); - unbind_evtchn_from_irq(np->evtchn); -} + if (xen_start_info->flags & SIF_INITDOMAIN) + return 0; -static void vif_resume(struct net_private *np) -{ - /* - * Connect regardless of whether IFF_UP flag set. - * Stop bad things from happening until we're back up. - */ - np->backend_state = BEST_DISCONNECTED; - memset(np->tx, 0, PAGE_SIZE); - memset(np->rx, 0, PAGE_SIZE); - - send_interface_connect(np); -} + IPRINTK("Initialising virtual ethernet driver.\n"); -void netif_suspend(void) -{ - struct list_head *ent; - struct net_private *np; - - list_for_each (ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - vif_suspend(np); - } + (void)register_inetaddr_notifier(¬ifier_inetdev); + + return xenbus_register_frontend(&netfront); } +module_init(netif_init); + -void netif_resume(void) +static void __exit netif_exit(void) { - struct list_head *ent; - struct net_private *np; + unregister_inetaddr_notifier(¬ifier_inetdev); - list_for_each (ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - vif_resume(np); - } + return xenbus_unregister_driver(&netfront); } +module_exit(netif_exit); - -module_init(netif_init); - +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/privcmd/Makefile b/drivers/xen/privcmd/Makefile index e21869553..de090ba6b 100644 --- a/drivers/xen/privcmd/Makefile +++ b/drivers/xen/privcmd/Makefile @@ -1,2 +1,2 @@ -obj-y := privcmd.o +obj-$(CONFIG_XEN_PRIVCMD) := privcmd.o diff --git a/drivers/xen/privcmd/privcmd.c b/drivers/xen/privcmd/privcmd.c index 0b78cc7e8..3c9bb9f0d 100644 --- a/drivers/xen/privcmd/privcmd.c +++ b/drivers/xen/privcmd/privcmd.c @@ -19,214 +19,268 @@ #include #include #include +#include +#include #include #include #include #include -#include -#include -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define pud_t pgd_t -#define pud_offset(d, va) d -#endif +#include +#include +#include +#include +#include static struct proc_dir_entry *privcmd_intf; +static struct proc_dir_entry *capabilities_intf; + +#define NR_HYPERCALLS 64 +static DECLARE_BITMAP(hypercall_permission_map, NR_HYPERCALLS); static int privcmd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long data) + unsigned int cmd, unsigned long data) { - int ret = -ENOSYS; + int ret = -ENOSYS; + void __user *udata = (void __user *) data; - switch ( cmd ) - { - case IOCTL_PRIVCMD_HYPERCALL: - { - privcmd_hypercall_t hypercall; + switch (cmd) { + case IOCTL_PRIVCMD_HYPERCALL: { + privcmd_hypercall_t hypercall; - if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) - return -EFAULT; + if (copy_from_user(&hypercall, udata, sizeof(hypercall))) + return -EFAULT; + + /* Check hypercall number for validity. */ + if (hypercall.op >= NR_HYPERCALLS) + return -EINVAL; + if (!test_bit(hypercall.op, hypercall_permission_map)) + return -EINVAL; #if defined(__i386__) - __asm__ __volatile__ ( - "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; " - "movl 4(%%eax),%%ebx ;" - "movl 8(%%eax),%%ecx ;" - "movl 12(%%eax),%%edx ;" - "movl 16(%%eax),%%esi ;" - "movl 20(%%eax),%%edi ;" - "movl (%%eax),%%eax ;" - TRAP_INSTR "; " - "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" - : "=a" (ret) : "0" (&hypercall) : "memory" ); + __asm__ __volatile__ ( + "pushl %%ebx; pushl %%ecx; pushl %%edx; " + "pushl %%esi; pushl %%edi; " + "movl 8(%%eax),%%ebx ;" + "movl 16(%%eax),%%ecx ;" + "movl 24(%%eax),%%edx ;" + "movl 32(%%eax),%%esi ;" + "movl 40(%%eax),%%edi ;" + "movl (%%eax),%%eax ;" + "shll $5,%%eax ;" + "addl $hypercall_page,%%eax ;" + "call *%%eax ;" + "popl %%edi; popl %%esi; popl %%edx; " + "popl %%ecx; popl %%ebx" + : "=a" (ret) : "0" (&hypercall) : "memory" ); #elif defined (__x86_64__) - __asm__ __volatile__ ( - "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR - : "=a" (ret) - : "a" ((unsigned long)hypercall.op), - "D" ((unsigned long)hypercall.arg[0]), - "S" ((unsigned long)hypercall.arg[1]), - "d" ((unsigned long)hypercall.arg[2]), - "g" ((unsigned long)hypercall.arg[3]), - "g" ((unsigned long)hypercall.arg[4]) - : "r11","rcx","r8","r10","memory"); + { + long ign1, ign2, ign3; + __asm__ __volatile__ ( + "movq %8,%%r10; movq %9,%%r8;" + "shlq $5,%%rax ;" + "addq $hypercall_page,%%rax ;" + "call *%%rax" + : "=a" (ret), "=D" (ign1), + "=S" (ign2), "=d" (ign3) + : "0" ((unsigned long)hypercall.op), + "1" ((unsigned long)hypercall.arg[0]), + "2" ((unsigned long)hypercall.arg[1]), + "3" ((unsigned long)hypercall.arg[2]), + "g" ((unsigned long)hypercall.arg[3]), + "g" ((unsigned long)hypercall.arg[4]) + : "r8", "r10", "memory" ); + } +#elif defined (__ia64__) + __asm__ __volatile__ ( + ";; mov r14=%2; mov r15=%3; " + "mov r16=%4; mov r17=%5; mov r18=%6;" + "mov r2=%1; break 0x1000;; mov %0=r8 ;;" + : "=r" (ret) + : "r" (hypercall.op), + "r" (hypercall.arg[0]), + "r" (hypercall.arg[1]), + "r" (hypercall.arg[2]), + "r" (hypercall.arg[3]), + "r" (hypercall.arg[4]) + : "r14","r15","r16","r17","r18","r2","r8","memory"); #endif - } - break; - - case IOCTL_PRIVCMD_INITDOMAIN_EVTCHN: - { - extern int initdom_ctrlif_domcontroller_port; - ret = initdom_ctrlif_domcontroller_port; - } - break; - + } + break; + #if defined(CONFIG_XEN_PRIVILEGED_GUEST) - case IOCTL_PRIVCMD_MMAP: - { + case IOCTL_PRIVCMD_MMAP: { #define PRIVCMD_MMAP_SZ 32 - privcmd_mmap_t mmapcmd; - privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p; - int i, rc; - - if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) ) - return -EFAULT; + privcmd_mmap_t mmapcmd; + privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ]; + privcmd_mmap_entry_t __user *p; + int i, rc; - p = mmapcmd.entry; + if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd))) + return -EFAULT; - for (i=0; iPRIVCMD_MMAP_SZ)? - PRIVCMD_MMAP_SZ:(mmapcmd.num-i); + p = mmapcmd.entry; + for (i = 0; i < mmapcmd.num; + i += PRIVCMD_MMAP_SZ, p += PRIVCMD_MMAP_SZ) { + int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)? + PRIVCMD_MMAP_SZ:(mmapcmd.num-i); - if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) ) - return -EFAULT; + if (copy_from_user(&msg, p, + n*sizeof(privcmd_mmap_entry_t))) + return -EFAULT; - for ( j = 0; j < n; j++ ) - { - struct vm_area_struct *vma = - find_vma( current->mm, msg[j].va ); - - if ( !vma ) - return -EINVAL; - - if ( msg[j].va > PAGE_OFFSET ) - return -EINVAL; - - if ( (msg[j].va + (msg[j].npages< vma->vm_end ) - return -EINVAL; - - if ( (rc = direct_remap_area_pages(vma->vm_mm, - msg[j].va&PAGE_MASK, - msg[j].mfn<vm_page_prot, - mmapcmd.dom)) < 0 ) - return rc; - } - } - ret = 0; - } - break; - - case IOCTL_PRIVCMD_MMAPBATCH: - { - mmu_update_t u; - privcmd_mmapbatch_t m; - struct vm_area_struct *vma = NULL; - unsigned long *p, addr; - unsigned long mfn; - int i; - - if ( copy_from_user(&m, (void *)data, sizeof(m)) ) - { ret = -EFAULT; goto batch_err; } - - vma = find_vma( current->mm, m.addr ); - - if ( !vma ) - { ret = -EINVAL; goto batch_err; } - - if ( m.addr > PAGE_OFFSET ) - { ret = -EFAULT; goto batch_err; } - - if ( (m.addr + (m.num< vma->vm_end ) - { ret = -EFAULT; goto batch_err; } - - p = m.arr; - addr = m.addr; - for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ ) - { - if ( get_user(mfn, p) ) - return -EFAULT; - - u.val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot); - - __direct_remap_area_pages(vma->vm_mm, - addr, - PAGE_SIZE, - &u); - - if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0) ) - put_user(0xF0000000 | mfn, p); - } - - ret = 0; - break; - - batch_err: - printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n", - ret, vma, m.addr, m.num, m.arr, - vma ? vma->vm_start : 0, vma ? vma->vm_end : 0); - break; - } - break; + for (j = 0; j < n; j++) { + struct vm_area_struct *vma = + find_vma( current->mm, msg[j].va ); + + if (!vma) + return -EINVAL; + + if (msg[j].va > PAGE_OFFSET) + return -EINVAL; + + if ((msg[j].va + (msg[j].npages << PAGE_SHIFT)) + > vma->vm_end ) + return -EINVAL; + + if ((rc = direct_remap_pfn_range( + vma, + msg[j].va&PAGE_MASK, + msg[j].mfn, + msg[j].npages<vm_page_prot, + mmapcmd.dom)) < 0) + return rc; + } + } + ret = 0; + } + break; + + case IOCTL_PRIVCMD_MMAPBATCH: { + privcmd_mmapbatch_t m; + struct vm_area_struct *vma = NULL; + xen_pfn_t __user *p; + unsigned long addr, mfn; + int i; + + if (copy_from_user(&m, udata, sizeof(m))) { + ret = -EFAULT; + goto batch_err; + } + + if (m.dom == DOMID_SELF) { + ret = -EINVAL; + goto batch_err; + } + + vma = find_vma(current->mm, m.addr); + if (!vma) { + ret = -EINVAL; + goto batch_err; + } + + if (m.addr > PAGE_OFFSET) { + ret = -EFAULT; + goto batch_err; + } + + if ((m.addr + (m.num< vma->vm_end) { + ret = -EFAULT; + goto batch_err; + } + + p = m.arr; + addr = m.addr; + for (i = 0; i < m.num; i++, addr += PAGE_SIZE, p++) { + if (get_user(mfn, p)) + return -EFAULT; + + ret = direct_remap_pfn_range(vma, addr & PAGE_MASK, + mfn, PAGE_SIZE, + vma->vm_page_prot, m.dom); + if (ret < 0) + put_user(0xF0000000 | mfn, p); + } + + ret = 0; + break; + + batch_err: + printk("batch_err ret=%d vma=%p addr=%lx " + "num=%d arr=%p %lx-%lx\n", + ret, vma, (unsigned long)m.addr, m.num, m.arr, + vma ? vma->vm_start : 0, vma ? vma->vm_end : 0); + break; + } + break; #endif - case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN: - { - unsigned long m2pv = (unsigned long)machine_to_phys_mapping; - pgd_t *pgd = pgd_offset_k(m2pv); - pud_t *pud = pud_offset(pgd, m2pv); - pmd_t *pmd = pmd_offset(pud, m2pv); - unsigned long m2p_start_mfn = (*(unsigned long *)pmd) >> PAGE_SHIFT; - ret = put_user(m2p_start_mfn, (unsigned long *)data) ? -EFAULT: 0; - } - break; - - default: - ret = -EINVAL; - break; - } - return ret; + default: + ret = -EINVAL; + break; + } + + return ret; } +#ifndef HAVE_ARCH_PRIVCMD_MMAP static int privcmd_mmap(struct file * file, struct vm_area_struct * vma) { - /* DONTCOPY is essential for Xen as copy_page_range is broken. */ - vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY; + /* DONTCOPY is essential for Xen as copy_page_range is broken. */ + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY; - return 0; + return 0; } +#endif static struct file_operations privcmd_file_ops = { - ioctl : privcmd_ioctl, - mmap: privcmd_mmap + .ioctl = privcmd_ioctl, + .mmap = privcmd_mmap, }; - -static int __init privcmd_init(void) +static int capabilities_read(char *page, char **start, off_t off, + int count, int *eof, void *data) { - if ( !(xen_start_info.flags & SIF_PRIVILEGED) ) - return 0; + int len = 0; + *page = 0; - privcmd_intf = create_xen_proc_entry("privcmd", 0400); - if ( privcmd_intf != NULL ) - privcmd_intf->proc_fops = &privcmd_file_ops; + if (xen_start_info->flags & SIF_INITDOMAIN) + len = sprintf( page, "control_d\n" ); - return 0; + *eof = 1; + return len; +} + +static int __init privcmd_init(void) +{ + if (!is_running_on_xen()) + return -ENODEV; + + /* Set of hypercalls that privileged applications may execute. */ + set_bit(__HYPERVISOR_acm_op, hypercall_permission_map); + set_bit(__HYPERVISOR_dom0_op, hypercall_permission_map); + set_bit(__HYPERVISOR_event_channel_op, hypercall_permission_map); + set_bit(__HYPERVISOR_memory_op, hypercall_permission_map); + set_bit(__HYPERVISOR_mmu_update, hypercall_permission_map); + set_bit(__HYPERVISOR_mmuext_op, hypercall_permission_map); + set_bit(__HYPERVISOR_xen_version, hypercall_permission_map); + set_bit(__HYPERVISOR_sched_op, hypercall_permission_map); + set_bit(__HYPERVISOR_sched_op_compat, hypercall_permission_map); + set_bit(__HYPERVISOR_event_channel_op_compat, + hypercall_permission_map); + set_bit(__HYPERVISOR_hvm_op, hypercall_permission_map); + + privcmd_intf = create_xen_proc_entry("privcmd", 0400); + if (privcmd_intf != NULL) + privcmd_intf->proc_fops = &privcmd_file_ops; + + capabilities_intf = create_xen_proc_entry("capabilities", 0400 ); + if (capabilities_intf != NULL) + capabilities_intf->read_proc = capabilities_read; + + return 0; } __initcall(privcmd_init); diff --git a/fs/Kconfig b/fs/Kconfig index 0167990d8..1d0cf4054 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -842,6 +842,7 @@ config TMPFS config HUGETLBFS bool "HugeTLB file system support" depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN + depends !XEN help hugetlbfs is a filesystem backing for HugeTLB pages, based on ramfs. For architectures that support it, say Y here and read diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 68ebd10f3..aa50dc692 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -512,7 +512,11 @@ befs_utf2nls(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - int maxlen = in_len; /* The utf8->nls conversion can't make more chars */ + /* The utf8->nls conversion won't make the final nls string bigger + * than the utf one, but if the string is pure ascii they'll have the + * same width and an extra char is needed to save the additional \0 + */ + int maxlen = in_len + 1; befs_debug(sb, "---> utf2nls()"); @@ -588,7 +592,10 @@ befs_nls2utf(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - int maxlen = 3 * in_len; + /* There're nls characters that will translate to 3-chars-wide UTF-8 + * characters, a additional byte is needed to save the final \0 + * in special cases */ + int maxlen = (3 * in_len) + 1; befs_debug(sb, "---> nls2utf()\n"); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 093645b22..479ee5fde 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -88,7 +88,7 @@ static struct linux_binfmt elf_format = { .min_coredump = ELF_EXEC_PAGESIZE }; -#define BAD_ADDR(x) ((unsigned long)(x) > PAGE_MASK) +#define BAD_ADDR(x) ((unsigned long)(x) >= PAGE_MASK) static int set_brk(unsigned long start, unsigned long end) { @@ -441,7 +441,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, * <= p_memsize so it is only necessary to check p_memsz. */ k = load_addr + eppnt->p_vaddr; - if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz || + if (BAD_ADDR(k) || eppnt->p_filesz > eppnt->p_memsz || eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) { error = -ENOMEM; goto out_close; @@ -944,7 +944,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) * allowed task size. Note that p_filesz must always be * <= p_memsz so it is only necessary to check p_memsz. */ - if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || + if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || elf_ppnt->p_memsz > TASK_SIZE || TASK_SIZE - elf_ppnt->p_memsz < k) { /* set_brk can never work. Avoid overflows. */ @@ -1005,10 +1005,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) } } if (BAD_ADDR(elf_entry)) { - printk(KERN_ERR "Unable to load interpreter %.128s\n", - elf_interpreter); force_sig(SIGSEGV, current); - retval = -ENOEXEC; /* Nobody gets to see this, but.. */ + retval = IS_ERR((void *)elf_entry) ? + (int)elf_entry : -EINVAL; goto out_free_dentry; } reloc_func_desc = interp_load_addr; @@ -1019,8 +1018,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) } else { elf_entry = loc->elf_ex.e_entry; if (BAD_ADDR(elf_entry)) { - send_sig(SIGSEGV, current, 0); - retval = -ENOEXEC; /* Nobody gets to see this, but.. */ + force_sig(SIGSEGV, current); + retval = -EINVAL; goto out_free_dentry; } } diff --git a/fs/buffer.c b/fs/buffer.c index 23f1f3a68..7f6d65925 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -473,13 +473,18 @@ out: pass does the actual I/O. */ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { + struct address_space *mapping = bdev->bd_inode->i_mapping; + + if (mapping->nrpages == 0) + return; + invalidate_bh_lrus(); /* * FIXME: what about destroy_dirty_buffers? * We really want to use invalidate_inode_pages2() for * that, but not until that's cleaned up. */ - invalidate_inode_pages(bdev->bd_inode->i_mapping); + invalidate_inode_pages(mapping); } /* diff --git a/fs/ext2/super.c b/fs/ext2/super.c index f05b2cff4..22993252e 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -252,6 +252,46 @@ static struct super_operations ext2_sops = { #endif }; +static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) +{ + __u32 *objp = vobjp; + unsigned long ino = objp[0]; + __u32 generation = objp[1]; + struct inode *inode; + struct dentry *result; + + if (ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb)) + return ERR_PTR(-ESTALE); + if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count)) + return ERR_PTR(-ESTALE); + + /* iget isn't really right if the inode is currently unallocated!! + * ext2_read_inode currently does appropriate checks, but + * it might be "neater" to call ext2_get_inode first and check + * if the inode is valid..... + */ + inode = iget(sb, ino); + if (inode == NULL) + return ERR_PTR(-ENOMEM); + if (is_bad_inode(inode) + || (generation && inode->i_generation != generation) + ) { + /* we didn't find the right inode.. */ + iput(inode); + return ERR_PTR(-ESTALE); + } + /* now to find a dentry. + * If possible, get a well-connected one + */ + result = d_alloc_anon(inode); + if (!result) { + iput(inode); + return ERR_PTR(-ENOMEM); + } + return result; +} + + /* Yes, most of these are left as NULL!! * A NULL value implies the default, which works with ext2-like file * systems, but can be improved upon. @@ -259,6 +299,7 @@ static struct super_operations ext2_sops = { */ static struct export_operations ext2_export_ops = { .get_parent = ext2_get_parent, + .get_dentry = ext2_get_dentry, }; static unsigned long get_sb_block(void **data) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index bdd65f45d..4ce217b6d 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1160,7 +1160,7 @@ retry: ret = PTR_ERR(handle); goto out; } - if (test_opt(inode->i_sb, NOBH)) + if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_prepare_write(page, from, to, ext3_get_block); else ret = block_prepare_write(page, from, to, ext3_get_block); @@ -1246,7 +1246,7 @@ static int ext3_writeback_commit_write(struct file *file, struct page *page, if (new_i_size > EXT3_I(inode)->i_disksize) EXT3_I(inode)->i_disksize = new_i_size; - if (test_opt(inode->i_sb, NOBH)) + if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_commit_write(file, page, from, to); else ret = generic_commit_write(file, page, from, to); @@ -1496,7 +1496,7 @@ static int ext3_writeback_writepage(struct page *page, goto out_fail; } - if (test_opt(inode->i_sb, NOBH)) + if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_writepage(page, ext3_get_block, wbc); else ret = block_write_full_page(page, ext3_get_block, wbc); @@ -2403,14 +2403,15 @@ static unsigned long ext3_get_inode_block(struct super_block *sb, struct buffer_head *bh; struct ext3_group_desc * gdp; - - if ((ino != EXT3_ROOT_INO && ino != EXT3_JOURNAL_INO && - ino != EXT3_RESIZE_INO && ino < EXT3_FIRST_INO(sb)) || - ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) { - ext3_error(sb, "ext3_get_inode_block", - "bad inode number: %lu", ino); + if (!ext3_valid_inum(sb, ino)) { + /* + * This error is already checked for in namei.c unless we are + * looking at an NFS filehandle, in which case no error + * report is needed + */ return 0; } + block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb); if (block_group >= EXT3_SB(sb)->s_groups_count) { ext3_error(sb,"ext3_get_inode_block","group >= groups count"); diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 329eae367..045f58812 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1001,7 +1001,12 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str if (bh) { unsigned long ino = le32_to_cpu(de->inode); brelse (bh); - inode = iget(dir->i_sb, ino); + if (!ext3_valid_inum(dir->i_sb, ino)) { + ext3_error(dir->i_sb, "ext3_lookup", + "bad inode number: %lu", ino); + inode = NULL; + } else + inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); @@ -1030,7 +1035,13 @@ struct dentry *ext3_get_parent(struct dentry *child) return ERR_PTR(-ENOENT); ino = le32_to_cpu(de->inode); brelse(bh); - inode = iget(child->d_inode->i_sb, ino); + + if (!ext3_valid_inum(child->d_inode->i_sb, ino)) { + ext3_error(child->d_inode->i_sb, "ext3_get_parent", + "bad inode number: %lu", ino); + inode = NULL; + } else + inode = iget(child->d_inode->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 2a0cb4ca8..ed22106c9 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -620,8 +620,48 @@ static struct super_operations ext3_sops = { #endif }; +static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) +{ + __u32 *objp = vobjp; + unsigned long ino = objp[0]; + __u32 generation = objp[1]; + struct inode *inode; + struct dentry *result; + + if (ino != EXT3_ROOT_INO && ino < EXT3_FIRST_INO(sb)) + return ERR_PTR(-ESTALE); + if (ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) + return ERR_PTR(-ESTALE); + + /* iget isn't really right if the inode is currently unallocated!! + * ext3_read_inode currently does appropriate checks, but + * it might be "neater" to call ext3_get_inode first and check + * if the inode is valid..... + */ + inode = iget(sb, ino); + if (inode == NULL) + return ERR_PTR(-ENOMEM); + if (is_bad_inode(inode) + || (generation && inode->i_generation != generation) + ) { + /* we didn't find the right inode.. */ + iput(inode); + return ERR_PTR(-ESTALE); + } + /* now to find a dentry. + * If possible, get a well-connected one + */ + result = d_alloc_anon(inode); + if (!result) { + iput(inode); + return ERR_PTR(-ENOMEM); + } + return result; +} + static struct export_operations ext3_export_ops = { .get_parent = ext3_get_parent, + .get_dentry = ext3_get_dentry, }; enum { diff --git a/fs/file.c b/fs/file.c index 55f4e7022..4c2cacca4 100644 --- a/fs/file.c +++ b/fs/file.c @@ -277,11 +277,13 @@ static struct fdtable *alloc_fdtable(int nr) } while (nfds <= nr); new_fds = alloc_fd_array(nfds); if (!new_fds) - goto out; + goto out2; fdt->fd = new_fds; fdt->max_fds = nfds; fdt->free_files = NULL; return fdt; +out2: + nfds = fdt->max_fdset; out: if (new_openset) free_fdset(new_openset, nfds); diff --git a/fs/locks.c b/fs/locks.c index 7ec121cb3..718983409 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1409,8 +1409,9 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) if (!leases_enable) goto out; - error = lease_alloc(filp, arg, &fl); - if (error) + error = -ENOMEM; + fl = locks_alloc_lock(); + if (fl == NULL) goto out; locks_copy_lock(fl, lease); @@ -1418,6 +1419,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) locks_insert_lock(before, fl); *flp = fl; + error = 0; out: return error; } diff --git a/fs/namei.c b/fs/namei.c index 181922326..178e70e79 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1773,8 +1773,14 @@ do_link: if (error) goto exit_dput; error = __do_follow_link(&path, nd); - if (error) + if (error) { + /* Does someone understand code flow here? Or it is only + * me so stupid? Anathema to whoever designed this non-sense + * with "intent.open". + */ + release_open_intent(nd); return error; + } nd->flags &= ~LOOKUP_PARENT; if (nd->last_type == LAST_BIND) goto ok; diff --git a/fs/proc/base.c b/fs/proc/base.c index 8c880128d..f6e0c6274 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -631,6 +631,27 @@ static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) return proc_check_root(inode); } +static int proc_setattr(struct dentry *dentry, struct iattr *attr) +{ + int error; + struct inode *inode = dentry->d_inode; + + if (attr->ia_valid & ATTR_MODE) + return -EPERM; + + error = inode_change_ok(inode, attr); + if (!error) { + error = security_inode_setattr(dentry, attr); + if (!error) + error = inode_setattr(inode, attr); + } + return error; +} + +static struct inode_operations proc_def_inode_operations = { + .setattr = proc_setattr, +}; + static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd) { struct dentry *root; @@ -1022,6 +1043,7 @@ static struct file_operations proc_oom_adjust_operations = { static struct inode_operations proc_mem_inode_operations = { .permission = proc_permission, + .setattr = proc_setattr, }; #ifdef CONFIG_AUDITSYSCALL @@ -1219,7 +1241,8 @@ out: static struct inode_operations proc_pid_link_inode_operations = { .readlink = proc_pid_readlink, - .follow_link = proc_pid_follow_link + .follow_link = proc_pid_follow_link, + .setattr = proc_setattr, }; #define NUMBUF 10 @@ -1400,6 +1423,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st ei->task = NULL; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); + inode->i_op = &proc_def_inode_operations; if (!pid_alive(task)) goto out_unlock; @@ -1455,6 +1479,7 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) inode->i_uid = 0; inode->i_gid = 0; } + inode->i_mode &= ~(S_ISUID | S_ISGID); security_task_to_inode(task, inode); return 1; } @@ -1483,6 +1508,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) inode->i_uid = 0; inode->i_gid = 0; } + inode->i_mode &= ~(S_ISUID | S_ISGID); security_task_to_inode(task, inode); return 1; } @@ -1628,11 +1654,13 @@ static struct file_operations proc_task_operations = { static struct inode_operations proc_fd_inode_operations = { .lookup = proc_lookupfd, .permission = proc_permission, + .setattr = proc_setattr, }; static struct inode_operations proc_task_inode_operations = { .lookup = proc_task_lookup, .permission = proc_task_permission, + .setattr = proc_setattr, }; #ifdef CONFIG_SECURITY @@ -1943,10 +1971,12 @@ static struct file_operations proc_tid_base_operations = { static struct inode_operations proc_tgid_base_inode_operations = { .lookup = proc_tgid_base_lookup, + .setattr = proc_setattr, }; static struct inode_operations proc_tid_base_inode_operations = { .lookup = proc_tid_base_lookup, + .setattr = proc_setattr, }; #ifdef CONFIG_SECURITY @@ -1988,10 +2018,12 @@ static struct dentry *proc_tid_attr_lookup(struct inode *dir, static struct inode_operations proc_tgid_attr_inode_operations = { .lookup = proc_tgid_attr_lookup, + .setattr = proc_setattr, }; static struct inode_operations proc_tid_attr_inode_operations = { .lookup = proc_tid_attr_lookup, + .setattr = proc_setattr, }; #endif @@ -2016,6 +2048,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) static struct inode_operations proc_self_inode_operations = { .readlink = proc_self_readlink, .follow_link = proc_self_follow_link, + .setattr = proc_setattr, }; /** diff --git a/fs/splice.c b/fs/splice.c index a285fd746..8fef6672b 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1294,6 +1294,85 @@ asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, return error; } +/* + * Make sure there's data to read. Wait for input if we can, otherwise + * return an appropriate error. + */ +static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags) +{ + int ret; + + /* + * Check ->nrbufs without the inode lock first. This function + * is speculative anyways, so missing one is ok. + */ + if (pipe->nrbufs) + return 0; + + ret = 0; + mutex_lock(&pipe->inode->i_mutex); + + while (!pipe->nrbufs) { + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + if (!pipe->writers) + break; + if (!pipe->waiting_writers) { + if (flags & SPLICE_F_NONBLOCK) { + ret = -EAGAIN; + break; + } + } + pipe_wait(pipe); + } + + mutex_unlock(&pipe->inode->i_mutex); + return ret; +} + +/* + * Make sure there's writeable room. Wait for room if we can, otherwise + * return an appropriate error. + */ +static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) +{ + int ret; + + /* + * Check ->nrbufs without the inode lock first. This function + * is speculative anyways, so missing one is ok. + */ + if (pipe->nrbufs < PIPE_BUFFERS) + return 0; + + ret = 0; + mutex_lock(&pipe->inode->i_mutex); + + while (pipe->nrbufs >= PIPE_BUFFERS) { + if (!pipe->readers) { + send_sig(SIGPIPE, current, 0); + ret = -EPIPE; + break; + } + if (flags & SPLICE_F_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + pipe->waiting_writers++; + pipe_wait(pipe); + pipe->waiting_writers--; + } + + mutex_unlock(&pipe->inode->i_mutex); + return ret; +} + /* * Link contents of ipipe to opipe. */ @@ -1302,9 +1381,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, size_t len, unsigned int flags) { struct pipe_buffer *ibuf, *obuf; - int ret, do_wakeup, i, ipipe_first; - - ret = do_wakeup = ipipe_first = 0; + int ret = 0, i = 0, nbuf; /* * Potential ABBA deadlock, work around it by ordering lock @@ -1312,7 +1389,6 @@ static int link_pipe(struct pipe_inode_info *ipipe, * could deadlock (one doing tee from A -> B, the other from B -> A). */ if (ipipe->inode < opipe->inode) { - ipipe_first = 1; mutex_lock(&ipipe->inode->i_mutex); mutex_lock(&opipe->inode->i_mutex); } else { @@ -1320,118 +1396,55 @@ static int link_pipe(struct pipe_inode_info *ipipe, mutex_lock(&ipipe->inode->i_mutex); } - for (i = 0;; i++) { + do { if (!opipe->readers) { send_sig(SIGPIPE, current, 0); if (!ret) ret = -EPIPE; break; } - if (ipipe->nrbufs - i) { - ibuf = ipipe->bufs + ((ipipe->curbuf + i) & (PIPE_BUFFERS - 1)); - /* - * If we have room, fill this buffer - */ - if (opipe->nrbufs < PIPE_BUFFERS) { - int nbuf = (opipe->curbuf + opipe->nrbufs) & (PIPE_BUFFERS - 1); - - /* - * Get a reference to this pipe buffer, - * so we can copy the contents over. - */ - ibuf->ops->get(ipipe, ibuf); - - obuf = opipe->bufs + nbuf; - *obuf = *ibuf; - - /* - * Don't inherit the gift flag, we need to - * prevent multiple steals of this page. - */ - obuf->flags &= ~PIPE_BUF_FLAG_GIFT; - - if (obuf->len > len) - obuf->len = len; - - opipe->nrbufs++; - do_wakeup = 1; - ret += obuf->len; - len -= obuf->len; - - if (!len) - break; - if (opipe->nrbufs < PIPE_BUFFERS) - continue; - } - - /* - * We have input available, but no output room. - * If we already copied data, return that. If we - * need to drop the opipe lock, it must be ordered - * last to avoid deadlocks. - */ - if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) { - if (!ret) - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - if (!ret) - ret = -ERESTARTSYS; - break; - } - if (do_wakeup) { - smp_mb(); - if (waitqueue_active(&opipe->wait)) - wake_up_interruptible(&opipe->wait); - kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN); - do_wakeup = 0; - } + /* + * If we have iterated all input buffers or ran out of + * output room, break. + */ + if (i >= ipipe->nrbufs || opipe->nrbufs >= PIPE_BUFFERS) + break; - opipe->waiting_writers++; - pipe_wait(opipe); - opipe->waiting_writers--; - continue; - } + ibuf = ipipe->bufs + ((ipipe->curbuf + i) & (PIPE_BUFFERS - 1)); + nbuf = (opipe->curbuf + opipe->nrbufs) & (PIPE_BUFFERS - 1); /* - * No input buffers, do the usual checks for available - * writers and blocking and wait if necessary + * Get a reference to this pipe buffer, + * so we can copy the contents over. */ - if (!ipipe->writers) - break; - if (!ipipe->waiting_writers) { - if (ret) - break; - } + ibuf->ops->get(ipipe, ibuf); + + obuf = opipe->bufs + nbuf; + *obuf = *ibuf; + /* - * pipe_wait() drops the ipipe mutex. To avoid deadlocks - * with another process, we can only safely do that if - * the ipipe lock is ordered last. + * Don't inherit the gift flag, we need to + * prevent multiple steals of this page. */ - if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) { - if (!ret) - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - if (!ret) - ret = -ERESTARTSYS; - break; - } + obuf->flags &= ~PIPE_BUF_FLAG_GIFT; - if (waitqueue_active(&ipipe->wait)) - wake_up_interruptible_sync(&ipipe->wait); - kill_fasync(&ipipe->fasync_writers, SIGIO, POLL_OUT); + if (obuf->len > len) + obuf->len = len; - pipe_wait(ipipe); - } + opipe->nrbufs++; + ret += obuf->len; + len -= obuf->len; + i++; + } while (len); mutex_unlock(&ipipe->inode->i_mutex); mutex_unlock(&opipe->inode->i_mutex); - if (do_wakeup) { + /* + * If we put data in the output pipe, wakeup any potential readers. + */ + if (ret > 0) { smp_mb(); if (waitqueue_active(&opipe->wait)) wake_up_interruptible(&opipe->wait); @@ -1452,14 +1465,29 @@ static long do_tee(struct file *in, struct file *out, size_t len, { struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe; struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe; + int ret = -EINVAL; /* - * Link ipipe to the two output pipes, consuming as we go along. + * Duplicate the contents of ipipe to opipe without actually + * copying the data. */ - if (ipipe && opipe) - return link_pipe(ipipe, opipe, len, flags); + if (ipipe && opipe && ipipe != opipe) { + /* + * Keep going, unless we encounter an error. The ipipe/opipe + * ordering doesn't really matter. + */ + ret = link_ipipe_prep(ipipe, flags); + if (!ret) { + ret = link_opipe_prep(opipe, flags); + if (!ret) { + ret = link_pipe(ipipe, opipe, len, flags); + if (!ret && (flags & SPLICE_F_NONBLOCK)) + ret = -EAGAIN; + } + } + } - return -EINVAL; + return ret; } asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags) diff --git a/fs/udf/super.c b/fs/udf/super.c index e45789fe3..73fc0d8ae 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1653,7 +1653,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) iput(inode); goto error_out; } - sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_maxbytes = 1<<30; return 0; error_out: diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index e1b0e8cfe..0abd66ce3 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -239,37 +239,51 @@ void udf_truncate_extents(struct inode * inode) { if (offset) { - extoffset -= adsize; - etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1); - if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) - { - extoffset -= adsize; - elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); + /* + * OK, there is not extent covering inode->i_size and + * no extent above inode->i_size => truncate is + * extending the file by 'offset'. + */ + if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) || + (bh && extoffset == sizeof(struct allocExtDesc))) { + /* File has no extents at all! */ + memset(&eloc, 0x00, sizeof(kernel_lb_addr)); + elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); } - else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) - { - kernel_lb_addr neloc = { 0, 0 }; + else { extoffset -= adsize; - nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | - ((elen + offset + inode->i_sb->s_blocksize - 1) & - ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); - udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); - } - else - { - if (elen & (inode->i_sb->s_blocksize - 1)) + etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1); + if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) + { + extoffset -= adsize; + elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); + } + else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { + kernel_lb_addr neloc = { 0, 0 }; extoffset -= adsize; - elen = EXT_RECORDED_ALLOCATED | - ((elen + inode->i_sb->s_blocksize - 1) & + nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | + ((elen + offset + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); + udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); + } + else + { + if (elen & (inode->i_sb->s_blocksize - 1)) + { + extoffset -= adsize; + elen = EXT_RECORDED_ALLOCATED | + ((elen + inode->i_sb->s_blocksize - 1) & + ~(inode->i_sb->s_blocksize - 1)); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1); + } + memset(&eloc, 0x00, sizeof(kernel_lb_addr)); + elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); } - memset(&eloc, 0x00, sizeof(kernel_lb_addr)); - elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; - udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); } } } diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index ac511ab9c..0655cc3cb 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -970,7 +970,7 @@ xfs_dir2_leafn_remove( /* * One less used entry in the free table. */ - free->hdr.nused = cpu_to_be32(-1); + be32_add(&free->hdr.nused, -1); xfs_dir2_free_log_header(tp, fbp); /* * If this was the last entry in the table, we can diff --git a/include/asm-generic/mman.h b/include/asm-generic/mman.h index 3b41d2bb7..010ced7cf 100644 --- a/include/asm-generic/mman.h +++ b/include/asm-generic/mman.h @@ -39,4 +39,10 @@ #define MAP_ANON MAP_ANONYMOUS #define MAP_FILE 0 +#ifdef __KERNEL__ +#ifndef arch_mmap_check +#define arch_mmap_check(addr, len, flags) (0) +#endif +#endif + #endif diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index 288233fd7..87476de38 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -132,10 +132,12 @@ extern unsigned int nmi_watchdog; extern int disable_timer_pin_1; +#ifndef CONFIG_XEN void smp_send_timer_broadcast_ipi(struct pt_regs *regs); void switch_APIC_timer_to_ipi(void *cpumask); void switch_ipi_to_APIC_timer(void *cpumask); #define ARCH_APICTIMER_STOPS_ON_C3 1 +#endif extern int timer_over_8254; diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h index aa371537c..fdecfa0d1 100644 --- a/include/asm-i386/desc.h +++ b/include/asm-i386/desc.h @@ -170,7 +170,7 @@ static inline void set_user_cs(struct desc_struct *desc, unsigned long limit) } #define load_user_cs_desc(cpu, mm) \ - get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS] = (mm)->context.user_cs + get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS] = (mm)->context.user_cs extern void arch_add_exec_range(struct mm_struct *mm, unsigned long limit); extern void arch_remove_exec_range(struct mm_struct *mm, unsigned long limit); diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h index cfb1c61d3..f11513aa9 100644 --- a/include/asm-i386/fixmap.h +++ b/include/asm-i386/fixmap.h @@ -20,7 +20,7 @@ * Leave one empty page between vmalloc'ed areas and * the start of the fixmap. */ -#define __FIXADDR_TOP 0xfffff000 +extern unsigned long __FIXADDR_TOP; #ifndef __ASSEMBLY__ #include @@ -95,6 +95,8 @@ enum fixed_addresses { extern void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags); +extern void set_fixaddr_top(unsigned long top); + #define set_fixmap(idx, phys) \ __set_fixmap(idx, phys, PAGE_KERNEL) /* diff --git a/include/asm-i386/mach-default/mach_traps.h b/include/asm-i386/mach-default/mach_traps.h index 625438b8a..4e34a91be 100644 --- a/include/asm-i386/mach-default/mach_traps.h +++ b/include/asm-i386/mach-default/mach_traps.h @@ -15,6 +15,18 @@ static inline void clear_mem_error(unsigned char reason) outb(reason, 0x61); } +static inline void clear_io_check_error(unsigned char reason) +{ + unsigned long i; + + reason = (reason & 0xf) | 8; + outb(reason, 0x61); + i = 2000; + while (--i) udelay(1000); + reason &= ~8; + outb(reason, 0x61); +} + static inline unsigned char get_nmi_reason(void) { return inb(0x61); diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h index 104653b50..2b2683ea4 100644 --- a/include/asm-i386/page.h +++ b/include/asm-i386/page.h @@ -128,7 +128,7 @@ extern int devmem_is_allowed(unsigned long pagenr); #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE) -#define MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE) +#define MAXMEM (__FIXADDR_TOP-__PAGE_OFFSET-__VMALLOC_RESERVE) #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) diff --git a/include/asm-i386/pgtable-2level-defs.h b/include/asm-i386/pgtable-2level-defs.h index 02518079f..bd6346f41 100644 --- a/include/asm-i386/pgtable-2level-defs.h +++ b/include/asm-i386/pgtable-2level-defs.h @@ -1,6 +1,8 @@ #ifndef _I386_PGTABLE_2LEVEL_DEFS_H #define _I386_PGTABLE_2LEVEL_DEFS_H +#define HAVE_SHARED_KERNEL_PMD 0 + /* * traditional i386 two-level paging structure: */ diff --git a/include/asm-i386/pgtable-3level-defs.h b/include/asm-i386/pgtable-3level-defs.h index eb3a1ea88..0c7599201 100644 --- a/include/asm-i386/pgtable-3level-defs.h +++ b/include/asm-i386/pgtable-3level-defs.h @@ -1,6 +1,8 @@ #ifndef _I386_PGTABLE_3LEVEL_DEFS_H #define _I386_PGTABLE_3LEVEL_DEFS_H +#define HAVE_SHARED_KERNEL_PMD 1 + /* * PGDIR_SHIFT determines what a top-level page table entry can map */ diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index d76b7693c..6d794a373 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -36,7 +36,7 @@ "\n1:\t" \ "lock ; decb %0\n\t" \ "jns 5f\n" \ - "2:\t" \ + "2:\t" \ "testl $0x200, %1\n\t" \ "jz 4f\n\t" \ "sti\n" \ diff --git a/include/asm-ia64/mman.h b/include/asm-ia64/mman.h index 6ba179f12..b242f9522 100644 --- a/include/asm-ia64/mman.h +++ b/include/asm-ia64/mman.h @@ -8,6 +8,14 @@ * David Mosberger-Tang , Hewlett-Packard Co */ +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#define arch_mmap_check ia64_map_check_rgn +int ia64_map_check_rgn(unsigned long addr, unsigned long len, + unsigned long flags); +#endif +#endif + #include #define MAP_GROWSDOWN 0x00100 /* stack-like segment */ diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h index 9bd2f9bf3..6f807e019 100644 --- a/include/asm-ia64/sn/xp.h +++ b/include/asm-ia64/sn/xp.h @@ -60,23 +60,37 @@ * the bte_copy() once in the hope that the failure was due to a temporary * aberration (i.e., the link going down temporarily). * - * See bte_copy for definition of the input parameters. + * src - physical address of the source of the transfer. + * vdst - virtual address of the destination of the transfer. + * len - number of bytes to transfer from source to destination. + * mode - see bte_copy() for definition. + * notification - see bte_copy() for definition. * * Note: xp_bte_copy() should never be called while holding a spinlock. */ static inline bte_result_t -xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) +xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification) { bte_result_t ret; + u64 pdst = ia64_tpa(vdst); - ret = bte_copy(src, dest, len, mode, notification); + /* + * Ensure that the physically mapped memory is contiguous. + * + * We do this by ensuring that the memory is from region 7 only. + * If the need should arise to use memory from one of the other + * regions, then modify the BUG_ON() statement to ensure that the + * memory from that region is always physically contiguous. + */ + BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL); + ret = bte_copy(src, pdst, len, mode, notification); if (ret != BTE_SUCCESS) { if (!in_interrupt()) { cond_resched(); } - ret = bte_copy(src, dest, len, mode, notification); + ret = bte_copy(src, pdst, len, mode, notification); } return ret; diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h index aa3b8ace9..b454ad4e2 100644 --- a/include/asm-ia64/sn/xpc.h +++ b/include/asm-ia64/sn/xpc.h @@ -684,7 +684,9 @@ extern struct xpc_vars *xpc_vars; extern struct xpc_rsvd_page *xpc_rsvd_page; extern struct xpc_vars_part *xpc_vars_part; extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1]; -extern char xpc_remote_copy_buffer[]; +extern char *xpc_remote_copy_buffer; +extern void *xpc_remote_copy_buffer_base; +extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **); extern struct xpc_rsvd_page *xpc_rsvd_page_init(void); extern void xpc_allow_IPI_ops(void); extern void xpc_restrict_IPI_ops(void); diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h index 180277556..ffedf14f8 100644 --- a/include/asm-s390/futex.h +++ b/include/asm-s390/futex.h @@ -98,9 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - asm volatile(" cs %1,%4,0(%5)\n" + asm volatile(" sacf 256\n" + " cs %1,%4,0(%5)\n" "0: lr %0,%1\n" - "1:\n" + "1: sacf 0\n" #ifndef __s390x__ ".section __ex_table,\"a\"\n" " .align 4\n" diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h index 88d1886ab..95ecab588 100644 --- a/include/asm-sparc/mman.h +++ b/include/asm-sparc/mman.h @@ -2,6 +2,12 @@ #ifndef __SPARC_MMAN_H__ #define __SPARC_MMAN_H__ +#ifdef __KERNEL__ +#define arch_mmap_check sparc_mmap_check +int sparc_mmap_check(unsigned long addr, unsigned long len, + unsigned long flags); +#endif + #include /* SunOS'ified... */ diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h index 6fd878e61..b3002763c 100644 --- a/include/asm-sparc64/mman.h +++ b/include/asm-sparc64/mman.h @@ -2,6 +2,12 @@ #ifndef __SPARC64_MMAN_H__ #define __SPARC64_MMAN_H__ +#ifdef __KERNEL__ +#define arch_mmap_check sparc64_mmap_check +int sparc64_mmap_check(unsigned long addr, unsigned long len, + unsigned long flags); +#endif + #include /* SunOS'ified... */ diff --git a/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h index 5015bb8d6..89d42431e 100644 --- a/include/asm-sparc64/sfp-machine.h +++ b/include/asm-sparc64/sfp-machine.h @@ -34,7 +34,7 @@ #define _FP_MUL_MEAT_D(R,X,Y) \ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) #define _FP_MUL_MEAT_Q(R,X,Y) \ - _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) diff --git a/include/asm-um/page.h b/include/asm-um/page.h index 0f7229ce7..459311435 100644 --- a/include/asm-um/page.h +++ b/include/asm-um/page.h @@ -116,7 +116,7 @@ extern struct page *arch_validate(struct page *page, gfp_t mask, int order); #define HAVE_ARCH_VALIDATE #define devmem_is_allowed(x) 1 -extern void arch_free_page(struct page *page, int order); +extern int arch_free_page(struct page *page, int order); #define HAVE_ARCH_FREE_PAGE #include diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h index bdbd89356..79db75f17 100644 --- a/include/asm-x86_64/apic.h +++ b/include/asm-x86_64/apic.h @@ -105,11 +105,13 @@ extern int disable_timer_pin_1; extern void setup_threshold_lvt(unsigned long lvt_off); +#ifndef CONFIG_XEN void smp_send_timer_broadcast_ipi(void); void switch_APIC_timer_to_ipi(void *cpumask); void switch_ipi_to_APIC_timer(void *cpumask); #define ARCH_APICTIMER_STOPS_ON_C3 1 +#endif #endif /* CONFIG_X86_LOCAL_APIC */ diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h index 0df1715de..91f751ba0 100644 --- a/include/asm-x86_64/hw_irq.h +++ b/include/asm-x86_64/hw_irq.h @@ -127,7 +127,7 @@ asmlinkage void IRQ_NAME(nr); \ __asm__( \ "\n.p2align\n" \ "IRQ" #nr "_interrupt:\n\t" \ - "push $" #nr "-256 ; " \ + "push $~(" #nr ") ; " \ "jmp common_interrupt"); #if defined(CONFIG_X86_IO_APIC) diff --git a/include/asm-x86_64/ipi.h b/include/asm-x86_64/ipi.h index 2a5c162b7..be4bc7638 100644 --- a/include/asm-x86_64/ipi.h +++ b/include/asm-x86_64/ipi.h @@ -49,6 +49,7 @@ static inline int __prepare_ICR2 (unsigned int mask) return SET_APIC_DEST_FIELD(mask); } +#ifndef CONFIG_XEN_UNPRIVILEGED_GUEST static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) { /* @@ -113,5 +114,6 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) } local_irq_restore(flags); } +#endif /* CONFIG_XEN_UNPRIVILEGED_GUEST */ #endif /* __ASM_IPI_H */ diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 31e83c3bd..195952b2c 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -21,7 +21,7 @@ extern unsigned long __supported_pte_mask; #define swapper_pg_dir init_level4_pgt -extern int nonx_setup(char *str); +extern void nonx_setup(const char *str); extern void paging_init(void); extern void clear_kernel_mapping(unsigned long addr, unsigned long size); diff --git a/include/linux/autoconf.h b/include/linux/autoconf.h index 546d52177..6b7b49be5 100644 --- a/include/linux/autoconf.h +++ b/include/linux/autoconf.h @@ -1,41 +1,62 @@ /* * Automatically generated C config: don't edit + * Linux kernel version: 2.6.17.13 + * Wed Oct 18 17:15:54 2006 */ #define AUTOCONF_INCLUDED +#define CONFIG_X86_32 1 +#define CONFIG_SEMAPHORE_SLEEPERS 1 #define CONFIG_X86 1 #define CONFIG_MMU 1 -#define CONFIG_UID16 1 #define CONFIG_GENERIC_ISA_DMA 1 +#define CONFIG_GENERIC_IOMAP 1 +#define CONFIG_GENERIC_HWEIGHT 1 +#define CONFIG_ARCH_MAY_HAVE_PC_FDC 1 +#define CONFIG_DMI 1 /* * Code maturity level options */ #define CONFIG_EXPERIMENTAL 1 -#define CONFIG_CLEAN_COMPILE 1 -#define CONFIG_STANDALONE 1 +#define CONFIG_BROKEN_ON_SMP 1 +#define CONFIG_INIT_ENV_ARG_LIMIT 32 /* * General setup */ +#define CONFIG_LOCALVERSION "" +#undef CONFIG_LOCALVERSION_AUTO #define CONFIG_SWAP 1 #define CONFIG_SYSVIPC 1 #define CONFIG_POSIX_MQUEUE 1 #define CONFIG_BSD_PROCESS_ACCT 1 +#undef CONFIG_BSD_PROCESS_ACCT_V3 #define CONFIG_SYSCTL 1 -#undef CONFIG_AUDIT -#define CONFIG_LOG_BUF_SHIFT 17 -#define CONFIG_HOTPLUG 1 +#define CONFIG_AUDIT 1 +#define CONFIG_AUDITSYSCALL 1 #undef CONFIG_IKCONFIG +#define CONFIG_RELAY 1 +#define CONFIG_INITRAMFS_SOURCE "" +#define CONFIG_UID16 1 +#define CONFIG_VM86 1 +#define CONFIG_CC_OPTIMIZE_FOR_SIZE 1 #undef CONFIG_EMBEDDED #define CONFIG_KALLSYMS 1 #undef CONFIG_KALLSYMS_ALL +#define CONFIG_KALLSYMS_EXTRA_PASS 1 +#define CONFIG_HOTPLUG 1 +#define CONFIG_PRINTK 1 +#define CONFIG_BUG 1 +#define CONFIG_ELF_CORE 1 +#define CONFIG_BASE_FULL 1 #define CONFIG_FUTEX 1 #define CONFIG_EPOLL 1 -#define CONFIG_IOSCHED_NOOP 1 -#define CONFIG_IOSCHED_AS 1 -#define CONFIG_IOSCHED_DEADLINE 1 -#define CONFIG_IOSCHED_CFQ 1 -#define CONFIG_CC_OPTIMIZE_FOR_SIZE 1 +#define CONFIG_SHMEM 1 +#define CONFIG_SLAB 1 +#undef CONFIG_TINY_SHMEM +#define CONFIG_BASE_SMALL 0 +#undef CONFIG_SLOB +#define CONFIG_OBSOLETE_INTERMODULE_MODULE 1 /* * Loadable module support @@ -43,24 +64,46 @@ #define CONFIG_MODULES 1 #define CONFIG_MODULE_UNLOAD 1 #undef CONFIG_MODULE_FORCE_UNLOAD -#define CONFIG_OBSOLETE_MODPARM 1 -#undef CONFIG_MODVERSIONS +#define CONFIG_MODVERSIONS 1 +#define CONFIG_MODULE_SRCVERSION_ALL 1 +#define CONFIG_MODULE_SIG 1 +#undef CONFIG_MODULE_SIG_FORCE #define CONFIG_KMOD 1 -#define CONFIG_STOP_MACHINE 1 + +/* + * Block layer + */ +#define CONFIG_LBD 1 +#define CONFIG_BLK_DEV_IO_TRACE 1 +#define CONFIG_LSF 1 + +/* + * IO Schedulers + */ +#define CONFIG_IOSCHED_NOOP 1 +#define CONFIG_IOSCHED_AS 1 +#define CONFIG_IOSCHED_DEADLINE 1 +#define CONFIG_IOSCHED_CFQ 1 +#undef CONFIG_DEFAULT_AS +#undef CONFIG_DEFAULT_DEADLINE +#define CONFIG_DEFAULT_CFQ 1 +#undef CONFIG_DEFAULT_NOOP +#define CONFIG_DEFAULT_IOSCHED "cfq" /* * Processor type and features */ -#undef CONFIG_X86_PC +#undef CONFIG_SMP +#define CONFIG_X86_PC 1 +#undef CONFIG_X86_XEN #undef CONFIG_X86_ELAN #undef CONFIG_X86_VOYAGER #undef CONFIG_X86_NUMAQ #undef CONFIG_X86_SUMMIT #undef CONFIG_X86_BIGSMP #undef CONFIG_X86_VISWS -#define CONFIG_X86_GENERICARCH 1 +#undef CONFIG_X86_GENERICARCH #undef CONFIG_X86_ES7000 -#define CONFIG_X86_CYCLONE_TIMER 1 #undef CONFIG_M386 #undef CONFIG_M486 #undef CONFIG_M586 @@ -75,9 +118,12 @@ #undef CONFIG_MK7 #undef CONFIG_MK8 #undef CONFIG_MCRUSOE +#undef CONFIG_MEFFICEON #undef CONFIG_MWINCHIPC6 #undef CONFIG_MWINCHIP2 #undef CONFIG_MWINCHIP3D +#undef CONFIG_MGEODEGX1 +#undef CONFIG_MGEODE_LX #undef CONFIG_MCYRIXIII #undef CONFIG_MVIAC3_2 #define CONFIG_X86_GENERIC 1 @@ -85,85 +131,111 @@ #define CONFIG_X86_XADD 1 #define CONFIG_X86_L1_CACHE_SHIFT 7 #define CONFIG_RWSEM_XCHGADD_ALGORITHM 1 +#define CONFIG_GENERIC_CALIBRATE_DELAY 1 #define CONFIG_X86_PPRO_FENCE 1 #define CONFIG_X86_WP_WORKS_OK 1 #define CONFIG_X86_INVLPG 1 #define CONFIG_X86_BSWAP 1 #define CONFIG_X86_POPAD_OK 1 +#define CONFIG_X86_CMPXCHG64 1 #define CONFIG_X86_GOOD_APIC 1 #define CONFIG_X86_INTEL_USERCOPY 1 #define CONFIG_X86_USE_PPRO_CHECKSUM 1 -#define CONFIG_X86_4G 1 -#define CONFIG_X86_SWITCH_PAGETABLES 1 -#define CONFIG_X86_4G_VM_LAYOUT 1 -#define CONFIG_X86_UACCESS_INDIRECT 1 -#define CONFIG_X86_HIGH_ENTRY 1 +#define CONFIG_X86_TSC 1 #define CONFIG_HPET_TIMER 1 #define CONFIG_HPET_EMULATE_RTC 1 -#define CONFIG_SMP 1 -#define CONFIG_NR_CPUS 32 -#define CONFIG_SCHED_SMT 1 +#undef CONFIG_PREEMPT_NONE +#define CONFIG_PREEMPT_VOLUNTARY 1 #undef CONFIG_PREEMPT +#define CONFIG_X86_UP_APIC 1 +#define CONFIG_X86_UP_IOAPIC 1 #define CONFIG_X86_LOCAL_APIC 1 #define CONFIG_X86_IO_APIC 1 -#define CONFIG_X86_TSC 1 #define CONFIG_X86_MCE 1 #undef CONFIG_X86_MCE_NONFATAL #define CONFIG_X86_MCE_P4THERMAL 1 #define CONFIG_TOSHIBA_MODULE 1 #define CONFIG_I8K_MODULE 1 +#undef CONFIG_X86_REBOOTFIXUPS #define CONFIG_MICROCODE_MODULE 1 #define CONFIG_X86_MSR_MODULE 1 #define CONFIG_X86_CPUID_MODULE 1 +#undef CONFIG_SWIOTLB /* * Firmware Drivers */ #define CONFIG_EDD_MODULE 1 +#define CONFIG_EFI_VARS 1 +#define CONFIG_DELL_RBU_MODULE 1 +#define CONFIG_DCDBAS_MODULE 1 #undef CONFIG_NOHIGHMEM -#undef CONFIG_HIGHMEM4G -#define CONFIG_HIGHMEM64G 1 +#define CONFIG_HIGHMEM4G 1 +#undef CONFIG_HIGHMEM64G +#define CONFIG_PAGE_OFFSET 0xC0000000 #define CONFIG_HIGHMEM 1 -#define CONFIG_X86_PAE 1 -#undef CONFIG_NUMA +#define CONFIG_ARCH_FLATMEM_ENABLE 1 +#define CONFIG_ARCH_SPARSEMEM_ENABLE 1 +#define CONFIG_ARCH_SELECT_MEMORY_MODEL 1 +#define CONFIG_SELECT_MEMORY_MODEL 1 +#define CONFIG_FLATMEM_MANUAL 1 +#undef CONFIG_DISCONTIGMEM_MANUAL +#undef CONFIG_SPARSEMEM_MANUAL +#define CONFIG_FLATMEM 1 +#define CONFIG_FLAT_NODE_MEM_MAP 1 +#define CONFIG_SPARSEMEM_STATIC 1 +#define CONFIG_SPLIT_PTLOCK_CPUS 4096 #define CONFIG_HIGHPTE 1 #undef CONFIG_MATH_EMULATION #define CONFIG_MTRR 1 -#undef CONFIG_EFI -#undef CONFIG_IRQBALANCE -#define CONFIG_HAVE_DEC_LOCK 1 +#define CONFIG_EFI 1 +#define CONFIG_BOOT_IOREMAP 1 #define CONFIG_REGPARM 1 +#undef CONFIG_SECCOMP +#undef CONFIG_HZ_100 +#define CONFIG_HZ_250 1 +#undef CONFIG_HZ_1000 +#define CONFIG_HZ 250 +#define CONFIG_KEXEC 1 +#undef CONFIG_CRASH_DUMP +#define CONFIG_PHYSICAL_START 0x400000 +#define CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG 1 /* * Power management options (ACPI, APM) */ #define CONFIG_PM 1 -#undef CONFIG_SOFTWARE_SUSPEND -#undef CONFIG_PM_DISK +#define CONFIG_PM_LEGACY 1 +#define CONFIG_PM_DEBUG 1 +#define CONFIG_SOFTWARE_SUSPEND 1 +#define CONFIG_PM_STD_PARTITION "" /* * ACPI (Advanced Configuration and Power Interface) Support */ #define CONFIG_ACPI 1 -#define CONFIG_ACPI_BOOT 1 -#define CONFIG_ACPI_INTERPRETER 1 #define CONFIG_ACPI_SLEEP 1 #define CONFIG_ACPI_SLEEP_PROC_FS 1 +#undef CONFIG_ACPI_SLEEP_PROC_SLEEP #define CONFIG_ACPI_AC_MODULE 1 #define CONFIG_ACPI_BATTERY_MODULE 1 #define CONFIG_ACPI_BUTTON_MODULE 1 +#define CONFIG_ACPI_VIDEO_MODULE 1 +#undef CONFIG_ACPI_HOTKEY #define CONFIG_ACPI_FAN 1 #define CONFIG_ACPI_PROCESSOR 1 #define CONFIG_ACPI_THERMAL 1 #define CONFIG_ACPI_ASUS_MODULE 1 +#define CONFIG_ACPI_IBM_MODULE 1 +#define CONFIG_ACPI_IBM_DOCK 1 #define CONFIG_ACPI_TOSHIBA_MODULE 1 +#define CONFIG_ACPI_BLACKLIST_YEAR 1999 #undef CONFIG_ACPI_DEBUG -#define CONFIG_ACPI_BUS 1 #define CONFIG_ACPI_EC 1 #define CONFIG_ACPI_POWER 1 -#define CONFIG_ACPI_PCI 1 #define CONFIG_ACPI_SYSTEM 1 #define CONFIG_X86_PM_TIMER 1 +#undef CONFIG_ACPI_CONTAINER /* * APM (Advanced Power Management) BIOS Support @@ -181,34 +253,43 @@ * CPU Frequency scaling */ #define CONFIG_CPU_FREQ 1 -#undef CONFIG_CPU_FREQ_PROC_INTF +#define CONFIG_CPU_FREQ_TABLE 1 +#define CONFIG_CPU_FREQ_DEBUG 1 +#define CONFIG_CPU_FREQ_STAT_MODULE 1 +#define CONFIG_CPU_FREQ_STAT_DETAILS 1 #undef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE #define CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE 1 #define CONFIG_CPU_FREQ_GOV_PERFORMANCE 1 #define CONFIG_CPU_FREQ_GOV_POWERSAVE_MODULE 1 #define CONFIG_CPU_FREQ_GOV_USERSPACE 1 -#undef CONFIG_CPU_FREQ_24_API -#define CONFIG_CPU_FREQ_TABLE 1 +#define CONFIG_CPU_FREQ_GOV_ONDEMAND_MODULE 1 +#define CONFIG_CPU_FREQ_GOV_CONSERVATIVE_MODULE 1 /* * CPUFreq processor drivers */ #define CONFIG_X86_ACPI_CPUFREQ_MODULE 1 -#undef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF -#define CONFIG_X86_POWERNOW_K6_MODULE 1 +#undef CONFIG_X86_POWERNOW_K6 #define CONFIG_X86_POWERNOW_K7 1 -#define CONFIG_X86_POWERNOW_K8_MODULE 1 +#define CONFIG_X86_POWERNOW_K7_ACPI 1 +#define CONFIG_X86_POWERNOW_K8 1 +#define CONFIG_X86_POWERNOW_K8_ACPI 1 #undef CONFIG_X86_GX_SUSPMOD #define CONFIG_X86_SPEEDSTEP_CENTRINO 1 -#define CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE 1 #define CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI 1 +#define CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE 1 #define CONFIG_X86_SPEEDSTEP_ICH 1 -#define CONFIG_X86_SPEEDSTEP_SMI_MODULE 1 +#define CONFIG_X86_SPEEDSTEP_SMI 1 #define CONFIG_X86_P4_CLOCKMOD_MODULE 1 +#undef CONFIG_X86_CPUFREQ_NFORCE2 +#define CONFIG_X86_LONGRUN 1 + +/* + * shared options + */ +#undef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF #define CONFIG_X86_SPEEDSTEP_LIB 1 #undef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK -#define CONFIG_X86_LONGRUN 1 -#undef CONFIG_X86_LONGHAUL /* * Bus options (PCI, PCMCIA, EISA, MCA, ISA) @@ -217,810 +298,1029 @@ #undef CONFIG_PCI_GOBIOS #undef CONFIG_PCI_GOMMCONFIG #undef CONFIG_PCI_GODIRECT +#undef CONFIG_PCI_GOXEN_FE #define CONFIG_PCI_GOANY 1 #define CONFIG_PCI_BIOS 1 #define CONFIG_PCI_DIRECT 1 #define CONFIG_PCI_MMCONFIG 1 -#define CONFIG_PCI_USE_VECTOR 1 -#define CONFIG_PCI_LEGACY_PROC 1 -#undef CONFIG_PCI_NAMES +#define CONFIG_PCIEPORTBUS 1 +#define CONFIG_HOTPLUG_PCI_PCIE_MODULE 1 +#undef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE +#define CONFIG_PCI_MSI 1 +#undef CONFIG_PCI_DEBUG +#define CONFIG_ISA_DMA_API 1 #define CONFIG_ISA 1 #undef CONFIG_EISA #undef CONFIG_MCA #undef CONFIG_SCx200 /* - * PCMCIA/CardBus support + * PCCARD (PCMCIA/CardBus) support */ -#define CONFIG_PCMCIA_MODULE 1 +#define CONFIG_PCCARD 1 #undef CONFIG_PCMCIA_DEBUG -#define CONFIG_YENTA_MODULE 1 +#define CONFIG_PCMCIA 1 +#define CONFIG_PCMCIA_LOAD_CIS 1 +#define CONFIG_PCMCIA_IOCTL 1 #define CONFIG_CARDBUS 1 + +/* + * PC-card bridges + */ +#define CONFIG_YENTA 1 +#define CONFIG_YENTA_O2 1 +#define CONFIG_YENTA_RICOH 1 +#define CONFIG_YENTA_TI 1 +#define CONFIG_YENTA_ENE_TUNE 1 +#define CONFIG_YENTA_TOSHIBA 1 +#define CONFIG_PD6729_MODULE 1 #define CONFIG_I82092_MODULE 1 -#define CONFIG_I82365_MODULE 1 -#define CONFIG_TCIC_MODULE 1 +#undef CONFIG_I82365 +#undef CONFIG_TCIC #define CONFIG_PCMCIA_PROBE 1 +#define CONFIG_PCCARD_NONSTATIC 1 /* * PCI Hotplug Support */ #define CONFIG_HOTPLUG_PCI 1 -#undef CONFIG_HOTPLUG_PCI_FAKE +#define CONFIG_HOTPLUG_PCI_FAKE_MODULE 1 #define CONFIG_HOTPLUG_PCI_COMPAQ_MODULE 1 #undef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM #define CONFIG_HOTPLUG_PCI_IBM_MODULE 1 -#undef CONFIG_HOTPLUG_PCI_ACPI +#define CONFIG_HOTPLUG_PCI_ACPI_MODULE 1 +#define CONFIG_HOTPLUG_PCI_ACPI_IBM_MODULE 1 #undef CONFIG_HOTPLUG_PCI_CPCI -#define CONFIG_HOTPLUG_PCI_PCIE_MODULE 1 -#define CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE 1 -#define CONFIG_HOTPLUG_PCI_SHPC_MODULE 1 -#define CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE 1 +#undef CONFIG_HOTPLUG_PCI_SHPC /* * Executable file formats */ #define CONFIG_BINFMT_ELF 1 #undef CONFIG_BINFMT_AOUT -#define CONFIG_BINFMT_MISC_MODULE 1 +#define CONFIG_BINFMT_MISC 1 /* - * Device Drivers + * Networking */ +#define CONFIG_NET 1 /* - * Generic Driver Options + * Networking options */ -#define CONFIG_FW_LOADER 1 -#undef CONFIG_DEBUG_DRIVER +#undef CONFIG_NETDEBUG +#define CONFIG_PACKET 1 +#define CONFIG_PACKET_MMAP 1 +#define CONFIG_UNIX 1 +#define CONFIG_XFRM 1 +#define CONFIG_XFRM_USER 1 +#define CONFIG_NET_KEY_MODULE 1 +#define CONFIG_INET 1 +#define CONFIG_IP_MULTICAST 1 +#define CONFIG_IP_ADVANCED_ROUTER 1 +#define CONFIG_ASK_IP_FIB_HASH 1 +#undef CONFIG_IP_FIB_TRIE +#define CONFIG_IP_FIB_HASH 1 +#define CONFIG_IP_MULTIPLE_TABLES 1 +#define CONFIG_IP_ROUTE_FWMARK 1 +#define CONFIG_IP_ROUTE_MULTIPATH 1 +#undef CONFIG_IP_ROUTE_MULTIPATH_CACHED +#define CONFIG_IP_ROUTE_VERBOSE 1 +#undef CONFIG_IP_PNP +#define CONFIG_NET_IPIP_MODULE 1 +#define CONFIG_NET_IPGRE_MODULE 1 +#define CONFIG_NET_IPGRE_BROADCAST 1 +#define CONFIG_IP_MROUTE 1 +#define CONFIG_IP_PIMSM_V1 1 +#define CONFIG_IP_PIMSM_V2 1 +#undef CONFIG_ARPD +#define CONFIG_SYN_COOKIES 1 +#define CONFIG_INET_AH_MODULE 1 +#define CONFIG_INET_ESP_MODULE 1 +#define CONFIG_INET_IPCOMP_MODULE 1 +#define CONFIG_INET_XFRM_TUNNEL_MODULE 1 +#define CONFIG_INET_TUNNEL_MODULE 1 +#define CONFIG_INET_DIAG_MODULE 1 +#define CONFIG_INET_TCP_DIAG_MODULE 1 +#undef CONFIG_TCP_CONG_ADVANCED +#define CONFIG_TCP_CONG_BIC 1 /* - * Memory Technology Devices (MTD) + * IP: Virtual Server Configuration */ -#define CONFIG_MTD_MODULE 1 -#undef CONFIG_MTD_DEBUG -#define CONFIG_MTD_PARTITIONS_MODULE 1 -#define CONFIG_MTD_CONCAT_MODULE 1 -#define CONFIG_MTD_REDBOOT_PARTS_MODULE 1 -#define CONFIG_MTD_CMDLINE_PARTS_MODULE 1 +#define CONFIG_IP_VS_MODULE 1 +#undef CONFIG_IP_VS_DEBUG +#define CONFIG_IP_VS_TAB_BITS 12 /* - * User Modules And Translation Layers + * IPVS transport protocol load balancing support */ -#define CONFIG_MTD_CHAR_MODULE 1 -#define CONFIG_MTD_BLOCK_MODULE 1 -#define CONFIG_MTD_BLOCK_RO_MODULE 1 -#define CONFIG_FTL_MODULE 1 -#define CONFIG_NFTL_MODULE 1 -#define CONFIG_NFTL_RW 1 -#define CONFIG_INFTL_MODULE 1 +#define CONFIG_IP_VS_PROTO_TCP 1 +#define CONFIG_IP_VS_PROTO_UDP 1 +#define CONFIG_IP_VS_PROTO_ESP 1 +#define CONFIG_IP_VS_PROTO_AH 1 /* - * RAM/ROM/Flash chip drivers + * IPVS scheduler */ -#define CONFIG_MTD_CFI_MODULE 1 -#define CONFIG_MTD_JEDECPROBE_MODULE 1 -#define CONFIG_MTD_GEN_PROBE_MODULE 1 -#undef CONFIG_MTD_CFI_ADV_OPTIONS -#define CONFIG_MTD_CFI_INTELEXT_MODULE 1 -#define CONFIG_MTD_CFI_AMDSTD_MODULE 1 -#define CONFIG_MTD_CFI_STAA_MODULE 1 -#define CONFIG_MTD_RAM_MODULE 1 -#define CONFIG_MTD_ROM_MODULE 1 -#define CONFIG_MTD_ABSENT_MODULE 1 -#undef CONFIG_MTD_OBSOLETE_CHIPS +#define CONFIG_IP_VS_RR_MODULE 1 +#define CONFIG_IP_VS_WRR_MODULE 1 +#define CONFIG_IP_VS_LC_MODULE 1 +#define CONFIG_IP_VS_WLC_MODULE 1 +#define CONFIG_IP_VS_LBLC_MODULE 1 +#define CONFIG_IP_VS_LBLCR_MODULE 1 +#define CONFIG_IP_VS_DH_MODULE 1 +#define CONFIG_IP_VS_SH_MODULE 1 +#define CONFIG_IP_VS_SED_MODULE 1 +#define CONFIG_IP_VS_NQ_MODULE 1 /* - * Mapping drivers for chip access + * IPVS application helper */ -#define CONFIG_MTD_COMPLEX_MAPPINGS 1 -#undef CONFIG_MTD_PHYSMAP -#undef CONFIG_MTD_PNC2000 -#define CONFIG_MTD_SC520CDP_MODULE 1 -#define CONFIG_MTD_NETSC520_MODULE 1 -#define CONFIG_MTD_SBC_GXX_MODULE 1 -#define CONFIG_MTD_ELAN_104NC_MODULE 1 -#define CONFIG_MTD_SCx200_DOCFLASH_MODULE 1 -#define CONFIG_MTD_AMD76XROM_MODULE 1 -#define CONFIG_MTD_ICH2ROM_MODULE 1 -#define CONFIG_MTD_SCB2_FLASH_MODULE 1 -#undef CONFIG_MTD_NETtel -#undef CONFIG_MTD_DILNETPC -#define CONFIG_MTD_L440GX_MODULE 1 -#define CONFIG_MTD_PCI_MODULE 1 +#define CONFIG_IP_VS_FTP_MODULE 1 +#define CONFIG_IPV6_MODULE 1 +#define CONFIG_IPV6_PRIVACY 1 +#define CONFIG_IPV6_ROUTER_PREF 1 +#define CONFIG_IPV6_ROUTE_INFO 1 +#define CONFIG_INET6_AH_MODULE 1 +#define CONFIG_INET6_ESP_MODULE 1 +#define CONFIG_INET6_IPCOMP_MODULE 1 +#define CONFIG_INET6_XFRM_TUNNEL_MODULE 1 +#define CONFIG_INET6_TUNNEL_MODULE 1 +#define CONFIG_IPV6_TUNNEL_MODULE 1 +#define CONFIG_NETFILTER 1 +#undef CONFIG_NETFILTER_DEBUG +#define CONFIG_BRIDGE_NETFILTER 1 /* - * Self-contained MTD device drivers + * Core Netfilter Configuration + */ +#define CONFIG_NETFILTER_NETLINK_MODULE 1 +#define CONFIG_NETFILTER_NETLINK_QUEUE_MODULE 1 +#define CONFIG_NETFILTER_NETLINK_LOG_MODULE 1 +#define CONFIG_NETFILTER_XTABLES_MODULE 1 +#define CONFIG_NETFILTER_XT_TARGET_CLASSIFY_MODULE 1 +#define CONFIG_NETFILTER_XT_TARGET_CONNMARK_MODULE 1 +#define CONFIG_NETFILTER_XT_TARGET_MARK_MODULE 1 +#define CONFIG_NETFILTER_XT_TARGET_NFQUEUE_MODULE 1 +#define CONFIG_NETFILTER_XT_TARGET_NOTRACK_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_COMMENT_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_CONNBYTES_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_CONNMARK_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_CONNTRACK_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_DCCP_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_ESP_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_HELPER_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_LENGTH_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_LIMIT_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_MAC_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_MARK_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_POLICY_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_MULTIPORT_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_PHYSDEV_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_PKTTYPE_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_REALM_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_SCTP_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_STATE_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_STRING_MODULE 1 +#define CONFIG_NETFILTER_XT_MATCH_TCPMSS_MODULE 1 + +/* + * IP: Netfilter Configuration */ -#define CONFIG_MTD_PMC551_MODULE 1 -#undef CONFIG_MTD_PMC551_BUGFIX -#undef CONFIG_MTD_PMC551_DEBUG -#undef CONFIG_MTD_SLRAM -#define CONFIG_MTD_MTDRAM_MODULE 1 -#define CONFIG_MTDRAM_TOTAL_SIZE 4096 -#define CONFIG_MTDRAM_ERASE_SIZE 128 -#undef CONFIG_MTD_BLKMTD +#define CONFIG_IP_NF_CONNTRACK_MODULE 1 +#define CONFIG_IP_NF_CT_ACCT 1 +#define CONFIG_IP_NF_CONNTRACK_MARK 1 +#define CONFIG_IP_NF_CONNTRACK_EVENTS 1 +#define CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE 1 +#define CONFIG_IP_NF_CT_PROTO_SCTP_MODULE 1 +#define CONFIG_IP_NF_FTP_MODULE 1 +#define CONFIG_IP_NF_IRC_MODULE 1 +#define CONFIG_IP_NF_NETBIOS_NS_MODULE 1 +#define CONFIG_IP_NF_TFTP_MODULE 1 +#define CONFIG_IP_NF_AMANDA_MODULE 1 +#define CONFIG_IP_NF_PPTP_MODULE 1 +#define CONFIG_IP_NF_H323_MODULE 1 +#define CONFIG_IP_NF_QUEUE_MODULE 1 +#define CONFIG_IP_NF_IPTABLES_MODULE 1 +#define CONFIG_IP_NF_MATCH_IPRANGE_MODULE 1 +#define CONFIG_IP_NF_MATCH_TOS_MODULE 1 +#define CONFIG_IP_NF_MATCH_RECENT_MODULE 1 +#define CONFIG_IP_NF_MATCH_ECN_MODULE 1 +#define CONFIG_IP_NF_MATCH_DSCP_MODULE 1 +#define CONFIG_IP_NF_MATCH_AH_MODULE 1 +#define CONFIG_IP_NF_MATCH_TTL_MODULE 1 +#define CONFIG_IP_NF_MATCH_OWNER_MODULE 1 +#define CONFIG_IP_NF_MATCH_ADDRTYPE_MODULE 1 +#define CONFIG_IP_NF_MATCH_HASHLIMIT_MODULE 1 +#define CONFIG_IP_NF_FILTER_MODULE 1 +#define CONFIG_IP_NF_TARGET_REJECT_MODULE 1 +#define CONFIG_IP_NF_TARGET_LOG_MODULE 1 +#define CONFIG_IP_NF_TARGET_ULOG_MODULE 1 +#define CONFIG_IP_NF_TARGET_TCPMSS_MODULE 1 +#define CONFIG_IP_NF_NAT_MODULE 1 +#define CONFIG_IP_NF_NAT_NEEDED 1 +#define CONFIG_IP_NF_TARGET_MASQUERADE_MODULE 1 +#define CONFIG_IP_NF_TARGET_REDIRECT_MODULE 1 +#define CONFIG_IP_NF_TARGET_NETMAP_MODULE 1 +#define CONFIG_IP_NF_TARGET_SAME_MODULE 1 +#define CONFIG_IP_NF_NAT_SNMP_BASIC_MODULE 1 +#define CONFIG_IP_NF_NAT_IRC_MODULE 1 +#define CONFIG_IP_NF_NAT_FTP_MODULE 1 +#define CONFIG_IP_NF_NAT_TFTP_MODULE 1 +#define CONFIG_IP_NF_NAT_AMANDA_MODULE 1 +#define CONFIG_IP_NF_NAT_PPTP_MODULE 1 +#define CONFIG_IP_NF_NAT_H323_MODULE 1 +#define CONFIG_IP_NF_MANGLE_MODULE 1 +#define CONFIG_IP_NF_TARGET_TOS_MODULE 1 +#define CONFIG_IP_NF_TARGET_ECN_MODULE 1 +#define CONFIG_IP_NF_TARGET_DSCP_MODULE 1 +#define CONFIG_IP_NF_TARGET_TTL_MODULE 1 +#define CONFIG_IP_NF_TARGET_CLUSTERIP_MODULE 1 +#define CONFIG_IP_NF_RAW_MODULE 1 +#define CONFIG_IP_NF_ARPTABLES_MODULE 1 +#define CONFIG_IP_NF_ARPFILTER_MODULE 1 +#define CONFIG_IP_NF_ARP_MANGLE_MODULE 1 /* - * Disk-On-Chip Device Drivers + * IPv6: Netfilter Configuration (EXPERIMENTAL) */ -#define CONFIG_MTD_DOC2000_MODULE 1 -#undef CONFIG_MTD_DOC2001 -#define CONFIG_MTD_DOC2001PLUS_MODULE 1 -#define CONFIG_MTD_DOCPROBE_MODULE 1 -#undef CONFIG_MTD_DOCPROBE_ADVANCED -#define CONFIG_MTD_DOCPROBE_ADDRESS 0x0 +#define CONFIG_IP6_NF_QUEUE_MODULE 1 +#define CONFIG_IP6_NF_IPTABLES_MODULE 1 +#define CONFIG_IP6_NF_MATCH_RT_MODULE 1 +#define CONFIG_IP6_NF_MATCH_OPTS_MODULE 1 +#define CONFIG_IP6_NF_MATCH_FRAG_MODULE 1 +#define CONFIG_IP6_NF_MATCH_HL_MODULE 1 +#define CONFIG_IP6_NF_MATCH_OWNER_MODULE 1 +#define CONFIG_IP6_NF_MATCH_IPV6HEADER_MODULE 1 +#define CONFIG_IP6_NF_MATCH_AH_MODULE 1 +#define CONFIG_IP6_NF_MATCH_EUI64_MODULE 1 +#define CONFIG_IP6_NF_FILTER_MODULE 1 +#define CONFIG_IP6_NF_TARGET_LOG_MODULE 1 +#define CONFIG_IP6_NF_TARGET_REJECT_MODULE 1 +#define CONFIG_IP6_NF_MANGLE_MODULE 1 +#define CONFIG_IP6_NF_TARGET_HL_MODULE 1 +#define CONFIG_IP6_NF_RAW_MODULE 1 /* - * NAND Flash Device Drivers + * DECnet: Netfilter Configuration */ -#define CONFIG_MTD_NAND_MODULE 1 -#undef CONFIG_MTD_NAND_VERIFY_WRITE -#define CONFIG_MTD_NAND_IDS_MODULE 1 +#undef CONFIG_DECNET_NF_GRABULATOR /* - * Parallel port support + * Bridge: Netfilter Configuration */ -#define CONFIG_PARPORT_MODULE 1 -#define CONFIG_PARPORT_PC_MODULE 1 -#define CONFIG_PARPORT_PC_CML1_MODULE 1 -#define CONFIG_PARPORT_SERIAL_MODULE 1 -#undef CONFIG_PARPORT_PC_FIFO -#undef CONFIG_PARPORT_PC_SUPERIO -#define CONFIG_PARPORT_PC_PCMCIA_MODULE 1 -#undef CONFIG_PARPORT_OTHER -#define CONFIG_PARPORT_1284 1 +#define CONFIG_BRIDGE_NF_EBTABLES_MODULE 1 +#define CONFIG_BRIDGE_EBT_BROUTE_MODULE 1 +#define CONFIG_BRIDGE_EBT_T_FILTER_MODULE 1 +#define CONFIG_BRIDGE_EBT_T_NAT_MODULE 1 +#define CONFIG_BRIDGE_EBT_802_3_MODULE 1 +#define CONFIG_BRIDGE_EBT_AMONG_MODULE 1 +#define CONFIG_BRIDGE_EBT_ARP_MODULE 1 +#define CONFIG_BRIDGE_EBT_IP_MODULE 1 +#define CONFIG_BRIDGE_EBT_LIMIT_MODULE 1 +#define CONFIG_BRIDGE_EBT_MARK_MODULE 1 +#define CONFIG_BRIDGE_EBT_PKTTYPE_MODULE 1 +#define CONFIG_BRIDGE_EBT_STP_MODULE 1 +#define CONFIG_BRIDGE_EBT_VLAN_MODULE 1 +#define CONFIG_BRIDGE_EBT_ARPREPLY_MODULE 1 +#define CONFIG_BRIDGE_EBT_DNAT_MODULE 1 +#define CONFIG_BRIDGE_EBT_MARK_T_MODULE 1 +#define CONFIG_BRIDGE_EBT_REDIRECT_MODULE 1 +#define CONFIG_BRIDGE_EBT_SNAT_MODULE 1 +#define CONFIG_BRIDGE_EBT_LOG_MODULE 1 +#define CONFIG_BRIDGE_EBT_ULOG_MODULE 1 /* - * Plug and Play support + * DCCP Configuration (EXPERIMENTAL) */ -#define CONFIG_PNP 1 -#undef CONFIG_PNP_DEBUG +#define CONFIG_IP_DCCP_MODULE 1 +#define CONFIG_INET_DCCP_DIAG_MODULE 1 +#define CONFIG_IP_DCCP_ACKVEC 1 /* - * Protocols + * DCCP CCIDs Configuration (EXPERIMENTAL) */ -#define CONFIG_ISAPNP 1 -#undef CONFIG_PNPBIOS +#define CONFIG_IP_DCCP_CCID2_MODULE 1 +#define CONFIG_IP_DCCP_CCID3_MODULE 1 +#define CONFIG_IP_DCCP_TFRC_LIB_MODULE 1 /* - * Block devices + * DCCP Kernel Hacking */ -#define CONFIG_BLK_DEV_FD_MODULE 1 -#undef CONFIG_BLK_DEV_XD -#undef CONFIG_PARIDE -#define CONFIG_BLK_CPQ_DA_MODULE 1 -#define CONFIG_BLK_CPQ_CISS_DA_MODULE 1 -#define CONFIG_CISS_SCSI_TAPE 1 -#define CONFIG_BLK_DEV_DAC960_MODULE 1 -#define CONFIG_BLK_DEV_UMEM_MODULE 1 -#define CONFIG_BLK_DEV_LOOP_MODULE 1 -#define CONFIG_BLK_DEV_CRYPTOLOOP_MODULE 1 -#define CONFIG_BLK_DEV_NBD_MODULE 1 -#define CONFIG_BLK_DEV_CARMEL_MODULE 1 -#define CONFIG_BLK_DEV_RAM 1 -#define CONFIG_BLK_DEV_RAM_SIZE 16384 -#define CONFIG_BLK_DEV_INITRD 1 -#define CONFIG_LBD 1 +#undef CONFIG_IP_DCCP_DEBUG /* - * ATA/ATAPI/MFM/RLL support + * SCTP Configuration (EXPERIMENTAL) */ -#define CONFIG_IDE 1 -#define CONFIG_BLK_DEV_IDE 1 +#define CONFIG_IP_SCTP_MODULE 1 +#undef CONFIG_SCTP_DBG_MSG +#undef CONFIG_SCTP_DBG_OBJCNT +#undef CONFIG_SCTP_HMAC_NONE +#undef CONFIG_SCTP_HMAC_SHA1 +#define CONFIG_SCTP_HMAC_MD5 1 /* - * Please see Documentation/ide.txt for help/info on IDE drives + * TIPC Configuration (EXPERIMENTAL) */ -#undef CONFIG_BLK_DEV_HD_IDE -#define CONFIG_BLK_DEV_IDEDISK 1 -#define CONFIG_IDEDISK_MULTI_MODE 1 -#undef CONFIG_IDEDISK_STROKE -#define CONFIG_BLK_DEV_IDECS_MODULE 1 -#define CONFIG_BLK_DEV_IDECD 1 -#define CONFIG_BLK_DEV_IDETAPE_MODULE 1 -#define CONFIG_BLK_DEV_IDEFLOPPY 1 -#undef CONFIG_BLK_DEV_IDESCSI -#undef CONFIG_IDE_TASK_IOCTL -#undef CONFIG_IDE_TASKFILE_IO +#define CONFIG_TIPC_MODULE 1 +#undef CONFIG_TIPC_ADVANCED +#undef CONFIG_TIPC_DEBUG +#define CONFIG_ATM_MODULE 1 +#define CONFIG_ATM_CLIP_MODULE 1 +#undef CONFIG_ATM_CLIP_NO_ICMP +#define CONFIG_ATM_LANE_MODULE 1 +#undef CONFIG_ATM_MPOA +#define CONFIG_ATM_BR2684_MODULE 1 +#undef CONFIG_ATM_BR2684_IPFILTER +#define CONFIG_BRIDGE_MODULE 1 +#define CONFIG_VLAN_8021Q_MODULE 1 +#define CONFIG_DECNET_MODULE 1 +#define CONFIG_DECNET_ROUTER 1 +#define CONFIG_DECNET_ROUTE_FWMARK 1 +#define CONFIG_LLC 1 +#undef CONFIG_LLC2 +#define CONFIG_IPX_MODULE 1 +#undef CONFIG_IPX_INTERN +#define CONFIG_ATALK_MODULE 1 +#define CONFIG_DEV_APPLETALK 1 +#undef CONFIG_LTPC +#undef CONFIG_COPS +#define CONFIG_IPDDP_MODULE 1 +#define CONFIG_IPDDP_ENCAP 1 +#define CONFIG_IPDDP_DECAP 1 +#undef CONFIG_X25 +#undef CONFIG_LAPB +#define CONFIG_NET_DIVERT 1 +#undef CONFIG_ECONET +#define CONFIG_WAN_ROUTER_MODULE 1 /* - * IDE chipset support/bugfixes + * QoS and/or fair queueing */ -#define CONFIG_IDE_GENERIC 1 -#undef CONFIG_BLK_DEV_CMD640 -#define CONFIG_BLK_DEV_IDEPNP 1 -#define CONFIG_BLK_DEV_IDEPCI 1 -#define CONFIG_IDEPCI_SHARE_IRQ 1 -#undef CONFIG_BLK_DEV_OFFBOARD -#define CONFIG_BLK_DEV_GENERIC 1 -#undef CONFIG_BLK_DEV_OPTI621 -#define CONFIG_BLK_DEV_RZ1000 1 -#define CONFIG_BLK_DEV_IDEDMA_PCI 1 -#undef CONFIG_BLK_DEV_IDEDMA_FORCED -#define CONFIG_IDEDMA_PCI_AUTO 1 -#undef CONFIG_IDEDMA_ONLYDISK -#define CONFIG_BLK_DEV_ADMA 1 -#define CONFIG_BLK_DEV_AEC62XX 1 -#define CONFIG_BLK_DEV_ALI15X3 1 -#undef CONFIG_WDC_ALI15X3 -#define CONFIG_BLK_DEV_AMD74XX 1 -#define CONFIG_BLK_DEV_ATIIXP 1 -#define CONFIG_BLK_DEV_CMD64X 1 -#define CONFIG_BLK_DEV_TRIFLEX 1 -#define CONFIG_BLK_DEV_CY82C693 1 -#define CONFIG_BLK_DEV_CS5520 1 -#define CONFIG_BLK_DEV_CS5530 1 -#define CONFIG_BLK_DEV_HPT34X 1 -#undef CONFIG_HPT34X_AUTODMA -#define CONFIG_BLK_DEV_HPT366 1 -#undef CONFIG_BLK_DEV_SC1200 -#define CONFIG_BLK_DEV_PIIX 1 -#undef CONFIG_BLK_DEV_NS87415 -#define CONFIG_BLK_DEV_PDC202XX_OLD 1 -#undef CONFIG_PDC202XX_BURST -#define CONFIG_BLK_DEV_PDC202XX_NEW 1 -#define CONFIG_PDC202XX_FORCE 1 -#define CONFIG_BLK_DEV_SVWKS 1 -#define CONFIG_BLK_DEV_SIIMAGE 1 -#define CONFIG_BLK_DEV_SIS5513 1 -#define CONFIG_BLK_DEV_SLC90E66 1 -#undef CONFIG_BLK_DEV_TRM290 -#define CONFIG_BLK_DEV_VIA82CXXX 1 -#undef CONFIG_IDE_ARM -#undef CONFIG_IDE_CHIPSETS -#define CONFIG_BLK_DEV_IDEDMA 1 -#undef CONFIG_IDEDMA_IVB -#define CONFIG_IDEDMA_AUTO 1 -#undef CONFIG_BLK_DEV_HD +#define CONFIG_NET_SCHED 1 +#undef CONFIG_NET_SCH_CLK_JIFFIES +#define CONFIG_NET_SCH_CLK_GETTIMEOFDAY 1 +#undef CONFIG_NET_SCH_CLK_CPU /* - * SCSI device support + * Queueing/Scheduling */ -#define CONFIG_SCSI_MODULE 1 -#define CONFIG_SCSI_PROC_FS 1 +#define CONFIG_NET_SCH_CBQ_MODULE 1 +#define CONFIG_NET_SCH_HTB_MODULE 1 +#define CONFIG_NET_SCH_HFSC_MODULE 1 +#define CONFIG_NET_SCH_ATM_MODULE 1 +#define CONFIG_NET_SCH_PRIO_MODULE 1 +#define CONFIG_NET_SCH_RED_MODULE 1 +#define CONFIG_NET_SCH_SFQ_MODULE 1 +#define CONFIG_NET_SCH_TEQL_MODULE 1 +#define CONFIG_NET_SCH_TBF_MODULE 1 +#define CONFIG_NET_SCH_GRED_MODULE 1 +#define CONFIG_NET_SCH_DSMARK_MODULE 1 +#define CONFIG_NET_SCH_NETEM_MODULE 1 +#define CONFIG_NET_SCH_INGRESS_MODULE 1 /* - * SCSI support type (disk, tape, CD-ROM) + * Classification */ -#define CONFIG_BLK_DEV_SD_MODULE 1 -#define CONFIG_CHR_DEV_ST_MODULE 1 -#define CONFIG_CHR_DEV_OSST_MODULE 1 -#define CONFIG_BLK_DEV_SR_MODULE 1 -#define CONFIG_BLK_DEV_SR_VENDOR 1 -#define CONFIG_CHR_DEV_SG_MODULE 1 +#define CONFIG_NET_CLS 1 +#define CONFIG_NET_CLS_BASIC_MODULE 1 +#define CONFIG_NET_CLS_TCINDEX_MODULE 1 +#define CONFIG_NET_CLS_ROUTE4_MODULE 1 +#define CONFIG_NET_CLS_ROUTE 1 +#define CONFIG_NET_CLS_FW_MODULE 1 +#define CONFIG_NET_CLS_U32_MODULE 1 +#define CONFIG_CLS_U32_PERF 1 +#define CONFIG_CLS_U32_MARK 1 +#define CONFIG_NET_CLS_RSVP_MODULE 1 +#define CONFIG_NET_CLS_RSVP6_MODULE 1 +#define CONFIG_NET_EMATCH 1 +#define CONFIG_NET_EMATCH_STACK 32 +#define CONFIG_NET_EMATCH_CMP_MODULE 1 +#define CONFIG_NET_EMATCH_NBYTE_MODULE 1 +#define CONFIG_NET_EMATCH_U32_MODULE 1 +#define CONFIG_NET_EMATCH_META_MODULE 1 +#define CONFIG_NET_EMATCH_TEXT_MODULE 1 +#undef CONFIG_NET_CLS_ACT +#define CONFIG_NET_CLS_POLICE 1 +#define CONFIG_NET_CLS_IND 1 +#define CONFIG_NET_ESTIMATOR 1 /* - * Some SCSI devices (e.g. CD jukebox) support multiple LUNs + * Network testing */ -#undef CONFIG_SCSI_MULTI_LUN -#define CONFIG_SCSI_CONSTANTS 1 -#define CONFIG_SCSI_LOGGING 1 +#define CONFIG_NET_PKTGEN_MODULE 1 +#undef CONFIG_HAMRADIO +#define CONFIG_IRDA_MODULE 1 /* - * SCSI Transport Attributes + * IrDA protocols */ -#define CONFIG_SCSI_SPI_ATTRS_MODULE 1 -#define CONFIG_SCSI_FC_ATTRS_MODULE 1 +#define CONFIG_IRLAN_MODULE 1 +#define CONFIG_IRNET_MODULE 1 +#define CONFIG_IRCOMM_MODULE 1 +#undef CONFIG_IRDA_ULTRA /* - * SCSI low-level drivers + * IrDA options */ -#define CONFIG_BLK_DEV_3W_XXXX_RAID_MODULE 1 -#undef CONFIG_SCSI_7000FASST -#define CONFIG_SCSI_ACARD_MODULE 1 -#define CONFIG_SCSI_AHA152X_MODULE 1 -#define CONFIG_SCSI_AHA1542_MODULE 1 -#define CONFIG_SCSI_AACRAID_MODULE 1 -#define CONFIG_SCSI_AIC7XXX_MODULE 1 -#define CONFIG_AIC7XXX_CMDS_PER_DEVICE 4 -#define CONFIG_AIC7XXX_RESET_DELAY_MS 15000 -#undef CONFIG_AIC7XXX_BUILD_FIRMWARE -#undef CONFIG_AIC7XXX_DEBUG_ENABLE -#define CONFIG_AIC7XXX_DEBUG_MASK 0 -#undef CONFIG_AIC7XXX_REG_PRETTY_PRINT -#define CONFIG_SCSI_AIC7XXX_OLD_MODULE 1 -#define CONFIG_SCSI_AIC79XX_MODULE 1 -#define CONFIG_AIC79XX_CMDS_PER_DEVICE 4 -#define CONFIG_AIC79XX_RESET_DELAY_MS 15000 -#undef CONFIG_AIC79XX_BUILD_FIRMWARE -#undef CONFIG_AIC79XX_ENABLE_RD_STRM -#undef CONFIG_AIC79XX_DEBUG_ENABLE -#define CONFIG_AIC79XX_DEBUG_MASK 0 -#undef CONFIG_AIC79XX_REG_PRETTY_PRINT -#undef CONFIG_SCSI_DPT_I2O -#define CONFIG_SCSI_ADVANSYS_MODULE 1 -#define CONFIG_SCSI_IN2000_MODULE 1 -#define CONFIG_SCSI_MEGARAID_MODULE 1 -#define CONFIG_SCSI_SATA 1 -#define CONFIG_SCSI_SATA_SVW_MODULE 1 -#define CONFIG_SCSI_ATA_PIIX_MODULE 1 -#define CONFIG_SCSI_SATA_PROMISE_MODULE 1 -#define CONFIG_SCSI_SATA_SX4_MODULE 1 -#define CONFIG_SCSI_SATA_SIL_MODULE 1 -#define CONFIG_SCSI_SATA_SIS_MODULE 1 -#define CONFIG_SCSI_SATA_VIA_MODULE 1 -#define CONFIG_SCSI_SATA_VITESSE_MODULE 1 -#define CONFIG_SCSI_BUSLOGIC_MODULE 1 -#undef CONFIG_SCSI_OMIT_FLASHPOINT -#undef CONFIG_SCSI_CPQFCTS -#undef CONFIG_SCSI_DMX3191D -#undef CONFIG_SCSI_DTC3280 -#undef CONFIG_SCSI_EATA -#undef CONFIG_SCSI_EATA_PIO -#define CONFIG_SCSI_FUTURE_DOMAIN_MODULE 1 -#define CONFIG_SCSI_GDTH_MODULE 1 -#undef CONFIG_SCSI_GENERIC_NCR5380 -#undef CONFIG_SCSI_GENERIC_NCR5380_MMIO -#define CONFIG_SCSI_IPS_MODULE 1 -#define CONFIG_SCSI_INIA100_MODULE 1 -#define CONFIG_SCSI_PPA_MODULE 1 -#define CONFIG_SCSI_IMM_MODULE 1 -#undef CONFIG_SCSI_IZIP_EPP16 -#undef CONFIG_SCSI_IZIP_SLOW_CTR -#undef CONFIG_SCSI_NCR53C406A -#define CONFIG_SCSI_SYM53C8XX_2_MODULE 1 -#define CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE 1 -#define CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS 16 -#define CONFIG_SCSI_SYM53C8XX_MAX_TAGS 64 -#undef CONFIG_SCSI_SYM53C8XX_IOMAPPED -#undef CONFIG_SCSI_IPR -#undef CONFIG_SCSI_PAS16 -#undef CONFIG_SCSI_PSI240I -#define CONFIG_SCSI_QLOGIC_FAS_MODULE 1 -#define CONFIG_SCSI_QLOGIC_ISP_MODULE 1 -#undef CONFIG_SCSI_QLOGIC_FC -#define CONFIG_SCSI_QLOGIC_1280_MODULE 1 -#define CONFIG_SCSI_QLA2XXX_MODULE 1 -#define CONFIG_SCSI_QLA21XX_MODULE 1 -#define CONFIG_SCSI_QLA22XX_MODULE 1 -#define CONFIG_SCSI_QLA2300_MODULE 1 -#define CONFIG_SCSI_QLA2322_MODULE 1 -#define CONFIG_SCSI_QLA6312_MODULE 1 -#define CONFIG_SCSI_QLA6322_MODULE 1 -#undef CONFIG_SCSI_SYM53C416 -#undef CONFIG_SCSI_DC395x -#define CONFIG_SCSI_DC390T_MODULE 1 -#undef CONFIG_SCSI_T128 -#undef CONFIG_SCSI_U14_34F -#undef CONFIG_SCSI_ULTRASTOR -#undef CONFIG_SCSI_NSP32 -#undef CONFIG_SCSI_DEBUG +#define CONFIG_IRDA_CACHE_LAST_LSAP 1 +#define CONFIG_IRDA_FAST_RR 1 +#undef CONFIG_IRDA_DEBUG /* - * PCMCIA SCSI adapter support + * Infrared-port device drivers */ -#define CONFIG_PCMCIA_AHA152X_MODULE 1 -#define CONFIG_PCMCIA_FDOMAIN_MODULE 1 -#define CONFIG_PCMCIA_NINJA_SCSI_MODULE 1 -#define CONFIG_PCMCIA_QLOGIC_MODULE 1 -#define CONFIG_PCMCIA_SYM53C500_MODULE 1 /* - * Old CD-ROM drivers (not SCSI, not IDE) + * SIR device drivers */ -#undef CONFIG_CD_NO_IDESCSI +#define CONFIG_IRTTY_SIR_MODULE 1 /* - * Multi-device support (RAID and LVM) + * Dongle support */ -#define CONFIG_MD 1 -#define CONFIG_BLK_DEV_MD 1 -#define CONFIG_MD_LINEAR_MODULE 1 -#define CONFIG_MD_RAID0_MODULE 1 -#define CONFIG_MD_RAID1_MODULE 1 -#define CONFIG_MD_RAID5_MODULE 1 -#define CONFIG_MD_RAID6_MODULE 1 -#define CONFIG_MD_MULTIPATH_MODULE 1 -#define CONFIG_BLK_DEV_DM_MODULE 1 -#define CONFIG_DM_CRYPT_MODULE 1 +#define CONFIG_DONGLE 1 +#define CONFIG_ESI_DONGLE_MODULE 1 +#define CONFIG_ACTISYS_DONGLE_MODULE 1 +#define CONFIG_TEKRAM_DONGLE_MODULE 1 +#define CONFIG_TOIM3232_DONGLE_MODULE 1 +#define CONFIG_LITELINK_DONGLE_MODULE 1 +#define CONFIG_MA600_DONGLE_MODULE 1 +#define CONFIG_GIRBIL_DONGLE_MODULE 1 +#define CONFIG_MCP2120_DONGLE_MODULE 1 +#define CONFIG_OLD_BELKIN_DONGLE_MODULE 1 +#define CONFIG_ACT200L_DONGLE_MODULE 1 /* - * Fusion MPT device support + * Old SIR device drivers */ -#define CONFIG_FUSION_MODULE 1 -#define CONFIG_FUSION_MAX_SGE 40 -#undef CONFIG_FUSION_ISENSE -#define CONFIG_FUSION_CTL_MODULE 1 -#define CONFIG_FUSION_LAN_MODULE 1 +#define CONFIG_IRPORT_SIR_MODULE 1 /* - * IEEE 1394 (FireWire) support + * Old Serial dongle support */ -#define CONFIG_IEEE1394_MODULE 1 +#undef CONFIG_DONGLE_OLD /* - * Subsystem Options + * FIR device drivers */ -#undef CONFIG_IEEE1394_VERBOSEDEBUG -#define CONFIG_IEEE1394_OUI_DB 1 -#undef CONFIG_IEEE1394_EXTRA_CONFIG_ROMS +#define CONFIG_USB_IRDA_MODULE 1 +#define CONFIG_SIGMATEL_FIR_MODULE 1 +#define CONFIG_NSC_FIR_MODULE 1 +#define CONFIG_WINBOND_FIR_MODULE 1 +#define CONFIG_TOSHIBA_FIR_MODULE 1 +#define CONFIG_SMC_IRCC_FIR_MODULE 1 +#define CONFIG_ALI_FIR_MODULE 1 +#define CONFIG_VLSI_FIR_MODULE 1 +#define CONFIG_VIA_FIR_MODULE 1 +#define CONFIG_BT_MODULE 1 +#define CONFIG_BT_L2CAP_MODULE 1 +#define CONFIG_BT_SCO_MODULE 1 +#define CONFIG_BT_RFCOMM_MODULE 1 +#define CONFIG_BT_RFCOMM_TTY 1 +#define CONFIG_BT_BNEP_MODULE 1 +#define CONFIG_BT_BNEP_MC_FILTER 1 +#define CONFIG_BT_BNEP_PROTO_FILTER 1 +#define CONFIG_BT_CMTP_MODULE 1 +#define CONFIG_BT_HIDP_MODULE 1 /* - * Device Drivers + * Bluetooth device drivers */ -#undef CONFIG_IEEE1394_PCILYNX -#define CONFIG_IEEE1394_OHCI1394_MODULE 1 +#define CONFIG_BT_HCIUSB_MODULE 1 +#define CONFIG_BT_HCIUSB_SCO 1 +#define CONFIG_BT_HCIUART_MODULE 1 +#define CONFIG_BT_HCIUART_H4 1 +#define CONFIG_BT_HCIUART_BCSP 1 +#define CONFIG_BT_HCIBCM203X_MODULE 1 +#define CONFIG_BT_HCIBPA10X_MODULE 1 +#define CONFIG_BT_HCIBFUSB_MODULE 1 +#define CONFIG_BT_HCIDTL1_MODULE 1 +#define CONFIG_BT_HCIBT3C_MODULE 1 +#define CONFIG_BT_HCIBLUECARD_MODULE 1 +#define CONFIG_BT_HCIBTUART_MODULE 1 +#define CONFIG_BT_HCIVHCI_MODULE 1 +#define CONFIG_IEEE80211_MODULE 1 +#undef CONFIG_IEEE80211_DEBUG +#define CONFIG_IEEE80211_CRYPT_WEP_MODULE 1 +#define CONFIG_IEEE80211_CRYPT_CCMP_MODULE 1 +#define CONFIG_IEEE80211_CRYPT_TKIP_MODULE 1 +#define CONFIG_IEEE80211_SOFTMAC_MODULE 1 +#define CONFIG_IEEE80211_SOFTMAC_DEBUG 1 +#define CONFIG_TUX_MODULE 1 /* - * Protocol Drivers + * TUX options */ -#define CONFIG_IEEE1394_VIDEO1394_MODULE 1 -#define CONFIG_IEEE1394_SBP2_MODULE 1 -#undef CONFIG_IEEE1394_SBP2_PHYS_DMA -#undef CONFIG_IEEE1394_ETH1394 -#define CONFIG_IEEE1394_DV1394_MODULE 1 -#define CONFIG_IEEE1394_RAWIO_MODULE 1 -#define CONFIG_IEEE1394_CMP_MODULE 1 -#define CONFIG_IEEE1394_AMDTP_MODULE 1 +#define CONFIG_TUX_EXTCGI 1 +#define CONFIG_TUX_EXTENDED_LOG 1 +#undef CONFIG_TUX_DEBUG +#define CONFIG_WIRELESS_EXT 1 /* - * I2O device support + * Device Drivers */ -#define CONFIG_I2O_MODULE 1 -#define CONFIG_I2O_CONFIG_MODULE 1 -#define CONFIG_I2O_BLOCK_MODULE 1 -#define CONFIG_I2O_SCSI_MODULE 1 -#define CONFIG_I2O_PROC_MODULE 1 /* - * Networking support + * Generic Driver Options */ -#define CONFIG_NET 1 +#define CONFIG_STANDALONE 1 +#define CONFIG_PREVENT_FIRMWARE_BUILD 1 +#define CONFIG_FW_LOADER 1 +#undef CONFIG_DEBUG_DRIVER /* - * Networking options + * Connector - unified userspace <-> kernelspace linker */ -#define CONFIG_PACKET 1 -#define CONFIG_PACKET_MMAP 1 -#define CONFIG_NETLINK_DEV 1 -#define CONFIG_UNIX 1 -#define CONFIG_NET_KEY_MODULE 1 -#define CONFIG_INET 1 -#define CONFIG_IP_MULTICAST 1 -#define CONFIG_IP_ADVANCED_ROUTER 1 -#define CONFIG_IP_MULTIPLE_TABLES 1 -#define CONFIG_IP_ROUTE_FWMARK 1 -#define CONFIG_IP_ROUTE_NAT 1 -#define CONFIG_IP_ROUTE_MULTIPATH 1 -#define CONFIG_IP_ROUTE_TOS 1 -#define CONFIG_IP_ROUTE_VERBOSE 1 -#undef CONFIG_IP_PNP -#define CONFIG_NET_IPIP_MODULE 1 -#define CONFIG_NET_IPGRE_MODULE 1 -#define CONFIG_NET_IPGRE_BROADCAST 1 -#define CONFIG_IP_MROUTE 1 -#define CONFIG_IP_PIMSM_V1 1 -#define CONFIG_IP_PIMSM_V2 1 -#undef CONFIG_ARPD -#define CONFIG_SYN_COOKIES 1 -#define CONFIG_INET_AH_MODULE 1 -#define CONFIG_INET_ESP_MODULE 1 -#define CONFIG_INET_IPCOMP_MODULE 1 +#define CONFIG_CONNECTOR_MODULE 1 /* - * IP: Virtual Server Configuration + * Memory Technology Devices (MTD) */ -#define CONFIG_IP_VS_MODULE 1 -#undef CONFIG_IP_VS_DEBUG -#define CONFIG_IP_VS_TAB_BITS 12 +#define CONFIG_MTD_MODULE 1 +#undef CONFIG_MTD_DEBUG +#define CONFIG_MTD_CONCAT_MODULE 1 +#define CONFIG_MTD_PARTITIONS 1 +#define CONFIG_MTD_REDBOOT_PARTS_MODULE 1 +#define CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK -1 +#undef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED +#undef CONFIG_MTD_REDBOOT_PARTS_READONLY +#define CONFIG_MTD_CMDLINE_PARTS 1 /* - * IPVS transport protocol load balancing support + * User Modules And Translation Layers */ -#define CONFIG_IP_VS_PROTO_TCP 1 -#define CONFIG_IP_VS_PROTO_UDP 1 -#define CONFIG_IP_VS_PROTO_ESP 1 -#define CONFIG_IP_VS_PROTO_AH 1 +#define CONFIG_MTD_CHAR_MODULE 1 +#define CONFIG_MTD_BLOCK_MODULE 1 +#define CONFIG_MTD_BLOCK_RO_MODULE 1 +#define CONFIG_FTL_MODULE 1 +#define CONFIG_NFTL_MODULE 1 +#define CONFIG_NFTL_RW 1 +#define CONFIG_INFTL_MODULE 1 +#define CONFIG_RFD_FTL_MODULE 1 /* - * IPVS scheduler + * RAM/ROM/Flash chip drivers */ -#define CONFIG_IP_VS_RR_MODULE 1 -#define CONFIG_IP_VS_WRR_MODULE 1 -#define CONFIG_IP_VS_LC_MODULE 1 -#define CONFIG_IP_VS_WLC_MODULE 1 -#define CONFIG_IP_VS_LBLC_MODULE 1 -#define CONFIG_IP_VS_LBLCR_MODULE 1 -#define CONFIG_IP_VS_DH_MODULE 1 -#define CONFIG_IP_VS_SH_MODULE 1 -#define CONFIG_IP_VS_SED_MODULE 1 -#define CONFIG_IP_VS_NQ_MODULE 1 +#define CONFIG_MTD_CFI_MODULE 1 +#define CONFIG_MTD_JEDECPROBE_MODULE 1 +#define CONFIG_MTD_GEN_PROBE_MODULE 1 +#undef CONFIG_MTD_CFI_ADV_OPTIONS +#define CONFIG_MTD_MAP_BANK_WIDTH_1 1 +#define CONFIG_MTD_MAP_BANK_WIDTH_2 1 +#define CONFIG_MTD_MAP_BANK_WIDTH_4 1 +#undef CONFIG_MTD_MAP_BANK_WIDTH_8 +#undef CONFIG_MTD_MAP_BANK_WIDTH_16 +#undef CONFIG_MTD_MAP_BANK_WIDTH_32 +#define CONFIG_MTD_CFI_I1 1 +#define CONFIG_MTD_CFI_I2 1 +#undef CONFIG_MTD_CFI_I4 +#undef CONFIG_MTD_CFI_I8 +#define CONFIG_MTD_CFI_INTELEXT_MODULE 1 +#define CONFIG_MTD_CFI_AMDSTD_MODULE 1 +#define CONFIG_MTD_CFI_STAA_MODULE 1 +#define CONFIG_MTD_CFI_UTIL_MODULE 1 +#define CONFIG_MTD_RAM_MODULE 1 +#define CONFIG_MTD_ROM_MODULE 1 +#define CONFIG_MTD_ABSENT_MODULE 1 +#undef CONFIG_MTD_OBSOLETE_CHIPS /* - * IPVS application helper + * Mapping drivers for chip access */ -#define CONFIG_IP_VS_FTP_MODULE 1 -#define CONFIG_IPV6_MODULE 1 -#define CONFIG_IPV6_PRIVACY 1 -#define CONFIG_INET6_AH_MODULE 1 -#define CONFIG_INET6_ESP_MODULE 1 -#define CONFIG_INET6_IPCOMP_MODULE 1 -#define CONFIG_IPV6_TUNNEL_MODULE 1 -#define CONFIG_NETFILTER 1 -#undef CONFIG_NETFILTER_DEBUG -#define CONFIG_BRIDGE_NETFILTER 1 +#define CONFIG_MTD_COMPLEX_MAPPINGS 1 +#undef CONFIG_MTD_PHYSMAP +#undef CONFIG_MTD_PNC2000 +#define CONFIG_MTD_SC520CDP_MODULE 1 +#define CONFIG_MTD_NETSC520_MODULE 1 +#define CONFIG_MTD_TS5500_MODULE 1 +#undef CONFIG_MTD_SBC_GXX +#undef CONFIG_MTD_AMD76XROM +#undef CONFIG_MTD_ICHXROM +#define CONFIG_MTD_SCB2_FLASH_MODULE 1 +#undef CONFIG_MTD_NETtel +#undef CONFIG_MTD_DILNETPC +#undef CONFIG_MTD_L440GX +#define CONFIG_MTD_PCI_MODULE 1 +#undef CONFIG_MTD_PLATRAM /* - * IP: Netfilter Configuration + * Self-contained MTD device drivers */ -#define CONFIG_IP_NF_CONNTRACK_MODULE 1 -#define CONFIG_IP_NF_FTP_MODULE 1 -#define CONFIG_IP_NF_IRC_MODULE 1 -#define CONFIG_IP_NF_TFTP_MODULE 1 -#define CONFIG_IP_NF_AMANDA_MODULE 1 -#define CONFIG_IP_NF_QUEUE_MODULE 1 -#define CONFIG_IP_NF_IPTABLES_MODULE 1 -#define CONFIG_IP_NF_MATCH_LIMIT_MODULE 1 -#define CONFIG_IP_NF_MATCH_IPRANGE_MODULE 1 -#define CONFIG_IP_NF_MATCH_MAC_MODULE 1 -#define CONFIG_IP_NF_MATCH_PKTTYPE_MODULE 1 -#define CONFIG_IP_NF_MATCH_MARK_MODULE 1 -#define CONFIG_IP_NF_MATCH_MULTIPORT_MODULE 1 -#define CONFIG_IP_NF_MATCH_TOS_MODULE 1 -#define CONFIG_IP_NF_MATCH_RECENT_MODULE 1 -#define CONFIG_IP_NF_MATCH_ECN_MODULE 1 -#define CONFIG_IP_NF_MATCH_DSCP_MODULE 1 -#define CONFIG_IP_NF_MATCH_AH_ESP_MODULE 1 -#define CONFIG_IP_NF_MATCH_LENGTH_MODULE 1 -#define CONFIG_IP_NF_MATCH_TTL_MODULE 1 -#define CONFIG_IP_NF_MATCH_TCPMSS_MODULE 1 -#define CONFIG_IP_NF_MATCH_HELPER_MODULE 1 -#define CONFIG_IP_NF_MATCH_STATE_MODULE 1 -#define CONFIG_IP_NF_MATCH_CONNTRACK_MODULE 1 -#define CONFIG_IP_NF_MATCH_OWNER_MODULE 1 -#define CONFIG_IP_NF_MATCH_PHYSDEV_MODULE 1 -#define CONFIG_IP_NF_FILTER_MODULE 1 -#define CONFIG_IP_NF_TARGET_REJECT_MODULE 1 -#define CONFIG_IP_NF_NAT_MODULE 1 -#define CONFIG_IP_NF_NAT_NEEDED 1 -#define CONFIG_IP_NF_TARGET_MASQUERADE_MODULE 1 -#define CONFIG_IP_NF_TARGET_REDIRECT_MODULE 1 -#define CONFIG_IP_NF_TARGET_NETMAP_MODULE 1 -#define CONFIG_IP_NF_TARGET_SAME_MODULE 1 -#define CONFIG_IP_NF_NAT_LOCAL 1 -#define CONFIG_IP_NF_NAT_SNMP_BASIC_MODULE 1 -#define CONFIG_IP_NF_NAT_IRC_MODULE 1 -#define CONFIG_IP_NF_NAT_FTP_MODULE 1 -#define CONFIG_IP_NF_NAT_TFTP_MODULE 1 -#define CONFIG_IP_NF_NAT_AMANDA_MODULE 1 -#define CONFIG_IP_NF_MANGLE_MODULE 1 -#define CONFIG_IP_NF_TARGET_TOS_MODULE 1 -#define CONFIG_IP_NF_TARGET_ECN_MODULE 1 -#define CONFIG_IP_NF_TARGET_DSCP_MODULE 1 -#define CONFIG_IP_NF_TARGET_MARK_MODULE 1 -#define CONFIG_IP_NF_TARGET_CLASSIFY_MODULE 1 -#define CONFIG_IP_NF_TARGET_LOG_MODULE 1 -#define CONFIG_IP_NF_TARGET_ULOG_MODULE 1 -#define CONFIG_IP_NF_TARGET_TCPMSS_MODULE 1 -#define CONFIG_IP_NF_ARPTABLES_MODULE 1 -#define CONFIG_IP_NF_ARPFILTER_MODULE 1 -#define CONFIG_IP_NF_ARP_MANGLE_MODULE 1 -#undef CONFIG_IP_NF_COMPAT_IPCHAINS -#undef CONFIG_IP_NF_COMPAT_IPFWADM -#define CONFIG_IP_NF_TARGET_NOTRACK_MODULE 1 -#define CONFIG_IP_NF_RAW_MODULE 1 +#define CONFIG_MTD_PMC551_MODULE 1 +#undef CONFIG_MTD_PMC551_BUGFIX +#undef CONFIG_MTD_PMC551_DEBUG +#undef CONFIG_MTD_SLRAM +#undef CONFIG_MTD_PHRAM +#define CONFIG_MTD_MTDRAM_MODULE 1 +#define CONFIG_MTDRAM_TOTAL_SIZE 4096 +#define CONFIG_MTDRAM_ERASE_SIZE 128 +#define CONFIG_MTD_BLOCK2MTD_MODULE 1 /* - * IPv6: Netfilter Configuration + * Disk-On-Chip Device Drivers */ -#undef CONFIG_IP6_NF_QUEUE -#define CONFIG_IP6_NF_IPTABLES_MODULE 1 -#define CONFIG_IP6_NF_MATCH_LIMIT_MODULE 1 -#define CONFIG_IP6_NF_MATCH_MAC_MODULE 1 -#define CONFIG_IP6_NF_MATCH_RT_MODULE 1 -#define CONFIG_IP6_NF_MATCH_OPTS_MODULE 1 -#define CONFIG_IP6_NF_MATCH_FRAG_MODULE 1 -#define CONFIG_IP6_NF_MATCH_HL_MODULE 1 -#define CONFIG_IP6_NF_MATCH_MULTIPORT_MODULE 1 -#define CONFIG_IP6_NF_MATCH_OWNER_MODULE 1 -#define CONFIG_IP6_NF_MATCH_MARK_MODULE 1 -#define CONFIG_IP6_NF_MATCH_IPV6HEADER_MODULE 1 -#define CONFIG_IP6_NF_MATCH_AHESP_MODULE 1 -#define CONFIG_IP6_NF_MATCH_LENGTH_MODULE 1 -#define CONFIG_IP6_NF_MATCH_EUI64_MODULE 1 -#define CONFIG_IP6_NF_FILTER_MODULE 1 -#define CONFIG_IP6_NF_TARGET_LOG_MODULE 1 -#define CONFIG_IP6_NF_MANGLE_MODULE 1 -#define CONFIG_IP6_NF_TARGET_MARK_MODULE 1 -#define CONFIG_IP6_NF_RAW_MODULE 1 +#define CONFIG_MTD_DOC2000_MODULE 1 +#undef CONFIG_MTD_DOC2001 +#define CONFIG_MTD_DOC2001PLUS_MODULE 1 +#define CONFIG_MTD_DOCPROBE_MODULE 1 +#define CONFIG_MTD_DOCECC_MODULE 1 +#undef CONFIG_MTD_DOCPROBE_ADVANCED +#define CONFIG_MTD_DOCPROBE_ADDRESS 0x0 + +/* + * NAND Flash Device Drivers + */ +#define CONFIG_MTD_NAND_MODULE 1 +#undef CONFIG_MTD_NAND_VERIFY_WRITE +#define CONFIG_MTD_NAND_IDS_MODULE 1 +#undef CONFIG_MTD_NAND_DISKONCHIP +#define CONFIG_MTD_NAND_NANDSIM_MODULE 1 + +/* + * OneNAND Flash Device Drivers + */ +#undef CONFIG_MTD_ONENAND + +/* + * Parallel port support + */ +#define CONFIG_PARPORT_MODULE 1 +#define CONFIG_PARPORT_PC_MODULE 1 +#define CONFIG_PARPORT_SERIAL_MODULE 1 +#undef CONFIG_PARPORT_PC_FIFO +#undef CONFIG_PARPORT_PC_SUPERIO +#define CONFIG_PARPORT_PC_PCMCIA_MODULE 1 +#define CONFIG_PARPORT_NOT_PC 1 +#undef CONFIG_PARPORT_GSC +#define CONFIG_PARPORT_1284 1 + +/* + * Plug and Play support + */ +#define CONFIG_PNP 1 +#undef CONFIG_PNP_DEBUG + +/* + * Protocols + */ +#define CONFIG_ISAPNP 1 +#undef CONFIG_PNPBIOS +#define CONFIG_PNPACPI 1 + +/* + * Block devices + */ +#define CONFIG_BLK_DEV_FD_MODULE 1 +#undef CONFIG_BLK_DEV_XD +#define CONFIG_PARIDE_MODULE 1 +#define CONFIG_PARIDE_PARPORT_MODULE 1 + +/* + * Parallel IDE high-level drivers + */ +#define CONFIG_PARIDE_PD_MODULE 1 +#define CONFIG_PARIDE_PCD_MODULE 1 +#define CONFIG_PARIDE_PF_MODULE 1 +#define CONFIG_PARIDE_PT_MODULE 1 +#define CONFIG_PARIDE_PG_MODULE 1 + +/* + * Parallel IDE protocol modules + */ +#define CONFIG_PARIDE_ATEN_MODULE 1 +#define CONFIG_PARIDE_BPCK_MODULE 1 +#define CONFIG_PARIDE_BPCK6_MODULE 1 +#define CONFIG_PARIDE_COMM_MODULE 1 +#define CONFIG_PARIDE_DSTR_MODULE 1 +#define CONFIG_PARIDE_FIT2_MODULE 1 +#define CONFIG_PARIDE_FIT3_MODULE 1 +#define CONFIG_PARIDE_EPAT_MODULE 1 +#define CONFIG_PARIDE_EPATC8 1 +#define CONFIG_PARIDE_EPIA_MODULE 1 +#define CONFIG_PARIDE_FRIQ_MODULE 1 +#define CONFIG_PARIDE_FRPW_MODULE 1 +#define CONFIG_PARIDE_KBIC_MODULE 1 +#define CONFIG_PARIDE_KTTI_MODULE 1 +#define CONFIG_PARIDE_ON20_MODULE 1 +#define CONFIG_PARIDE_ON26_MODULE 1 +#define CONFIG_BLK_CPQ_DA_MODULE 1 +#define CONFIG_BLK_CPQ_CISS_DA_MODULE 1 +#define CONFIG_CISS_SCSI_TAPE 1 +#define CONFIG_BLK_DEV_DAC960_MODULE 1 +#define CONFIG_BLK_DEV_UMEM_MODULE 1 +#undef CONFIG_BLK_DEV_COW_COMMON +#define CONFIG_BLK_DEV_LOOP_MODULE 1 +#define CONFIG_BLK_DEV_CRYPTOLOOP_MODULE 1 +#define CONFIG_BLK_DEV_NBD_MODULE 1 +#define CONFIG_BLK_DEV_SX8_MODULE 1 +#define CONFIG_BLK_DEV_UB_MODULE 1 +#define CONFIG_BLK_DEV_RAM 1 +#define CONFIG_BLK_DEV_RAM_COUNT 16 +#define CONFIG_BLK_DEV_RAM_SIZE 16384 +#define CONFIG_BLK_DEV_INITRD 1 +#define CONFIG_CDROM_PKTCDVD_MODULE 1 +#define CONFIG_CDROM_PKTCDVD_BUFFERS 8 +#undef CONFIG_CDROM_PKTCDVD_WCACHE +#define CONFIG_ATA_OVER_ETH_MODULE 1 + +/* + * ATA/ATAPI/MFM/RLL support + */ +#define CONFIG_IDE 1 +#define CONFIG_BLK_DEV_IDE 1 + +/* + * Please see Documentation/ide.txt for help/info on IDE drives + */ +#undef CONFIG_BLK_DEV_IDE_SATA +#undef CONFIG_BLK_DEV_HD_IDE +#define CONFIG_BLK_DEV_IDEDISK 1 +#define CONFIG_IDEDISK_MULTI_MODE 1 +#define CONFIG_BLK_DEV_IDECS_MODULE 1 +#define CONFIG_BLK_DEV_IDECD 1 +#undef CONFIG_BLK_DEV_IDETAPE +#define CONFIG_BLK_DEV_IDEFLOPPY 1 +#define CONFIG_BLK_DEV_IDESCSI_MODULE 1 +#define CONFIG_IDE_TASK_IOCTL 1 + +/* + * IDE chipset support/bugfixes + */ +#define CONFIG_IDE_GENERIC 1 +#define CONFIG_BLK_DEV_CMD640 1 +#define CONFIG_BLK_DEV_CMD640_ENHANCED 1 +#define CONFIG_BLK_DEV_IDEPNP 1 +#define CONFIG_BLK_DEV_IDEPCI 1 +#define CONFIG_IDEPCI_SHARE_IRQ 1 +#undef CONFIG_BLK_DEV_OFFBOARD +#define CONFIG_BLK_DEV_GENERIC 1 +#undef CONFIG_BLK_DEV_OPTI621 +#define CONFIG_BLK_DEV_RZ1000 1 +#define CONFIG_BLK_DEV_IDEDMA_PCI 1 +#undef CONFIG_BLK_DEV_IDEDMA_FORCED +#define CONFIG_IDEDMA_PCI_AUTO 1 +#undef CONFIG_IDEDMA_ONLYDISK +#define CONFIG_BLK_DEV_AEC62XX 1 +#define CONFIG_BLK_DEV_ALI15X3 1 +#undef CONFIG_WDC_ALI15X3 +#define CONFIG_BLK_DEV_AMD74XX 1 +#define CONFIG_BLK_DEV_ATIIXP 1 +#define CONFIG_BLK_DEV_CMD64X 1 +#define CONFIG_BLK_DEV_TRIFLEX 1 +#define CONFIG_BLK_DEV_CY82C693 1 +#define CONFIG_BLK_DEV_CS5520 1 +#define CONFIG_BLK_DEV_CS5530 1 +#define CONFIG_BLK_DEV_CS5535 1 +#define CONFIG_BLK_DEV_HPT34X 1 +#undef CONFIG_HPT34X_AUTODMA +#define CONFIG_BLK_DEV_HPT366 1 +#undef CONFIG_BLK_DEV_SC1200 +#define CONFIG_BLK_DEV_PIIX 1 +#define CONFIG_BLK_DEV_IT821X 1 +#undef CONFIG_BLK_DEV_NS87415 +#define CONFIG_BLK_DEV_PDC202XX_OLD 1 +#undef CONFIG_PDC202XX_BURST +#define CONFIG_BLK_DEV_PDC202XX_NEW 1 +#define CONFIG_BLK_DEV_SVWKS 1 +#define CONFIG_BLK_DEV_SIIMAGE 1 +#define CONFIG_BLK_DEV_SIS5513 1 +#define CONFIG_BLK_DEV_SLC90E66 1 +#undef CONFIG_BLK_DEV_TRM290 +#define CONFIG_BLK_DEV_VIA82CXXX 1 +#undef CONFIG_IDE_ARM +#undef CONFIG_IDE_CHIPSETS +#define CONFIG_BLK_DEV_IDEDMA 1 +#undef CONFIG_IDEDMA_IVB +#define CONFIG_IDEDMA_AUTO 1 +#undef CONFIG_BLK_DEV_HD /* - * Bridge: Netfilter Configuration + * SCSI device support */ -#define CONFIG_BRIDGE_NF_EBTABLES_MODULE 1 -#define CONFIG_BRIDGE_EBT_BROUTE_MODULE 1 -#define CONFIG_BRIDGE_EBT_T_FILTER_MODULE 1 -#define CONFIG_BRIDGE_EBT_T_NAT_MODULE 1 -#define CONFIG_BRIDGE_EBT_802_3_MODULE 1 -#define CONFIG_BRIDGE_EBT_AMONG_MODULE 1 -#define CONFIG_BRIDGE_EBT_ARP_MODULE 1 -#define CONFIG_BRIDGE_EBT_IP_MODULE 1 -#define CONFIG_BRIDGE_EBT_LIMIT_MODULE 1 -#define CONFIG_BRIDGE_EBT_MARK_MODULE 1 -#define CONFIG_BRIDGE_EBT_PKTTYPE_MODULE 1 -#define CONFIG_BRIDGE_EBT_STP_MODULE 1 -#define CONFIG_BRIDGE_EBT_VLAN_MODULE 1 -#define CONFIG_BRIDGE_EBT_ARPREPLY_MODULE 1 -#define CONFIG_BRIDGE_EBT_DNAT_MODULE 1 -#define CONFIG_BRIDGE_EBT_MARK_T_MODULE 1 -#define CONFIG_BRIDGE_EBT_REDIRECT_MODULE 1 -#define CONFIG_BRIDGE_EBT_SNAT_MODULE 1 -#define CONFIG_BRIDGE_EBT_LOG_MODULE 1 -#define CONFIG_XFRM 1 -#define CONFIG_XFRM_USER 1 +#define CONFIG_RAID_ATTRS_MODULE 1 +#define CONFIG_SCSI_MODULE 1 +#define CONFIG_SCSI_PROC_FS 1 /* - * SCTP Configuration (EXPERIMENTAL) + * SCSI support type (disk, tape, CD-ROM) */ -#define CONFIG_IP_SCTP_MODULE 1 -#undef CONFIG_SCTP_DBG_MSG -#undef CONFIG_SCTP_DBG_OBJCNT -#undef CONFIG_SCTP_HMAC_NONE -#undef CONFIG_SCTP_HMAC_SHA1 -#define CONFIG_SCTP_HMAC_MD5 1 -#undef CONFIG_ATM -#define CONFIG_BRIDGE_MODULE 1 -#define CONFIG_VLAN_8021Q_MODULE 1 -#undef CONFIG_DECNET -#define CONFIG_LLC_MODULE 1 -#undef CONFIG_LLC2 -#define CONFIG_IPX_MODULE 1 -#undef CONFIG_IPX_INTERN -#define CONFIG_ATALK_MODULE 1 -#define CONFIG_DEV_APPLETALK 1 -#define CONFIG_LTPC_MODULE 1 -#define CONFIG_COPS_MODULE 1 -#define CONFIG_COPS_DAYNA 1 -#define CONFIG_COPS_TANGENT 1 -#define CONFIG_IPDDP_MODULE 1 -#define CONFIG_IPDDP_ENCAP 1 -#define CONFIG_IPDDP_DECAP 1 -#undef CONFIG_X25 -#undef CONFIG_LAPB -#define CONFIG_NET_DIVERT 1 -#undef CONFIG_ECONET -#define CONFIG_WAN_ROUTER_MODULE 1 -#undef CONFIG_NET_FASTROUTE -#undef CONFIG_NET_HW_FLOWCONTROL +#define CONFIG_BLK_DEV_SD_MODULE 1 +#define CONFIG_CHR_DEV_ST_MODULE 1 +#define CONFIG_CHR_DEV_OSST_MODULE 1 +#define CONFIG_BLK_DEV_SR_MODULE 1 +#define CONFIG_BLK_DEV_SR_VENDOR 1 +#define CONFIG_CHR_DEV_SG_MODULE 1 +#define CONFIG_CHR_DEV_SCH_MODULE 1 /* - * QoS and/or fair queueing + * Some SCSI devices (e.g. CD jukebox) support multiple LUNs */ -#define CONFIG_NET_SCHED 1 -#define CONFIG_NET_SCH_CBQ_MODULE 1 -#define CONFIG_NET_SCH_HTB_MODULE 1 -#define CONFIG_NET_SCH_HFSC_MODULE 1 -#define CONFIG_NET_SCH_CSZ_MODULE 1 -#define CONFIG_NET_SCH_PRIO_MODULE 1 -#define CONFIG_NET_SCH_RED_MODULE 1 -#define CONFIG_NET_SCH_SFQ_MODULE 1 -#define CONFIG_NET_SCH_TEQL_MODULE 1 -#define CONFIG_NET_SCH_TBF_MODULE 1 -#define CONFIG_NET_SCH_GRED_MODULE 1 -#define CONFIG_NET_SCH_DSMARK_MODULE 1 -#define CONFIG_NET_SCH_DELAY_MODULE 1 -#define CONFIG_NET_SCH_INGRESS_MODULE 1 -#define CONFIG_NET_QOS 1 -#define CONFIG_NET_ESTIMATOR 1 -#define CONFIG_NET_CLS 1 -#define CONFIG_NET_CLS_TCINDEX_MODULE 1 -#define CONFIG_NET_CLS_ROUTE4_MODULE 1 -#define CONFIG_NET_CLS_ROUTE 1 -#define CONFIG_NET_CLS_FW_MODULE 1 -#define CONFIG_NET_CLS_U32_MODULE 1 -#define CONFIG_NET_CLS_RSVP_MODULE 1 -#define CONFIG_NET_CLS_RSVP6_MODULE 1 -#define CONFIG_NET_CLS_POLICE 1 +#define CONFIG_SCSI_MULTI_LUN 1 +#define CONFIG_SCSI_CONSTANTS 1 +#define CONFIG_SCSI_LOGGING 1 /* - * Network testing + * SCSI Transport Attributes */ -#undef CONFIG_NET_PKTGEN -#define CONFIG_NETPOLL 1 -#undef CONFIG_NETPOLL_RX -#undef CONFIG_NETPOLL_TRAP -#define CONFIG_NET_POLL_CONTROLLER 1 -#undef CONFIG_HAMRADIO -#define CONFIG_IRDA_MODULE 1 +#define CONFIG_SCSI_SPI_ATTRS_MODULE 1 +#define CONFIG_SCSI_FC_ATTRS_MODULE 1 +#define CONFIG_SCSI_ISCSI_ATTRS_MODULE 1 +#define CONFIG_SCSI_SAS_ATTRS_MODULE 1 /* - * IrDA protocols + * SCSI low-level drivers */ -#define CONFIG_IRLAN_MODULE 1 -#define CONFIG_IRNET_MODULE 1 -#define CONFIG_IRCOMM_MODULE 1 -#undef CONFIG_IRDA_ULTRA +#define CONFIG_ISCSI_TCP_MODULE 1 +#define CONFIG_BLK_DEV_3W_XXXX_RAID_MODULE 1 +#define CONFIG_SCSI_3W_9XXX_MODULE 1 +#undef CONFIG_SCSI_7000FASST +#define CONFIG_SCSI_ACARD_MODULE 1 +#define CONFIG_SCSI_AHA152X_MODULE 1 +#define CONFIG_SCSI_AHA1542_MODULE 1 +#define CONFIG_SCSI_AACRAID_MODULE 1 +#define CONFIG_SCSI_AIC7XXX_MODULE 1 +#define CONFIG_AIC7XXX_CMDS_PER_DEVICE 4 +#define CONFIG_AIC7XXX_RESET_DELAY_MS 15000 +#undef CONFIG_AIC7XXX_DEBUG_ENABLE +#define CONFIG_AIC7XXX_DEBUG_MASK 0 +#undef CONFIG_AIC7XXX_REG_PRETTY_PRINT +#define CONFIG_SCSI_AIC7XXX_OLD_MODULE 1 +#define CONFIG_SCSI_AIC79XX_MODULE 1 +#define CONFIG_AIC79XX_CMDS_PER_DEVICE 4 +#define CONFIG_AIC79XX_RESET_DELAY_MS 15000 +#undef CONFIG_AIC79XX_ENABLE_RD_STRM +#undef CONFIG_AIC79XX_DEBUG_ENABLE +#define CONFIG_AIC79XX_DEBUG_MASK 0 +#undef CONFIG_AIC79XX_REG_PRETTY_PRINT +#undef CONFIG_SCSI_DPT_I2O +#define CONFIG_SCSI_ADVANSYS_MODULE 1 +#undef CONFIG_SCSI_IN2000 +#define CONFIG_MEGARAID_NEWGEN 1 +#define CONFIG_MEGARAID_MM_MODULE 1 +#define CONFIG_MEGARAID_MAILBOX_MODULE 1 +#define CONFIG_MEGARAID_LEGACY_MODULE 1 +#define CONFIG_MEGARAID_SAS_MODULE 1 +#define CONFIG_SCSI_SATA_MODULE 1 +#define CONFIG_SCSI_SATA_AHCI_MODULE 1 +#define CONFIG_SCSI_SATA_SVW_MODULE 1 +#define CONFIG_SCSI_ATA_PIIX_MODULE 1 +#define CONFIG_SCSI_SATA_MV_MODULE 1 +#define CONFIG_SCSI_SATA_NV_MODULE 1 +#define CONFIG_SCSI_PDC_ADMA_MODULE 1 +#define CONFIG_SCSI_SATA_QSTOR_MODULE 1 +#define CONFIG_SCSI_SATA_PROMISE_MODULE 1 +#define CONFIG_SCSI_SATA_SX4_MODULE 1 +#define CONFIG_SCSI_SATA_SIL_MODULE 1 +#define CONFIG_SCSI_SATA_SIL24_MODULE 1 +#define CONFIG_SCSI_SATA_SIS_MODULE 1 +#define CONFIG_SCSI_SATA_ULI_MODULE 1 +#define CONFIG_SCSI_SATA_VIA_MODULE 1 +#define CONFIG_SCSI_SATA_VITESSE_MODULE 1 +#define CONFIG_SCSI_SATA_INTEL_COMBINED 1 +#define CONFIG_SCSI_BUSLOGIC_MODULE 1 +#undef CONFIG_SCSI_OMIT_FLASHPOINT +#undef CONFIG_SCSI_DMX3191D +#undef CONFIG_SCSI_DTC3280 +#undef CONFIG_SCSI_EATA +#define CONFIG_SCSI_FUTURE_DOMAIN_MODULE 1 +#define CONFIG_SCSI_GDTH_MODULE 1 +#undef CONFIG_SCSI_GENERIC_NCR5380 +#undef CONFIG_SCSI_GENERIC_NCR5380_MMIO +#define CONFIG_SCSI_IPS_MODULE 1 +#define CONFIG_SCSI_INITIO_MODULE 1 +#define CONFIG_SCSI_INIA100_MODULE 1 +#define CONFIG_SCSI_PPA_MODULE 1 +#define CONFIG_SCSI_IMM_MODULE 1 +#undef CONFIG_SCSI_IZIP_EPP16 +#undef CONFIG_SCSI_IZIP_SLOW_CTR +#undef CONFIG_SCSI_NCR53C406A +#define CONFIG_SCSI_SYM53C8XX_2_MODULE 1 +#define CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE 1 +#define CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS 16 +#define CONFIG_SCSI_SYM53C8XX_MAX_TAGS 64 +#define CONFIG_SCSI_SYM53C8XX_MMIO 1 +#undef CONFIG_SCSI_IPR +#undef CONFIG_SCSI_PAS16 +#undef CONFIG_SCSI_PSI240I +#undef CONFIG_SCSI_QLOGIC_FAS +#define CONFIG_SCSI_QLOGIC_1280_MODULE 1 +#define CONFIG_SCSI_QLA_FC_MODULE 1 +#define CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE 1 +#define CONFIG_SCSI_QLA21XX_MODULE 1 +#define CONFIG_SCSI_QLA22XX_MODULE 1 +#define CONFIG_SCSI_QLA2300_MODULE 1 +#define CONFIG_SCSI_QLA2322_MODULE 1 +#define CONFIG_SCSI_QLA24XX_MODULE 1 +#define CONFIG_SCSI_LPFC_MODULE 1 +#undef CONFIG_SCSI_SYM53C416 +#define CONFIG_SCSI_DC395x_MODULE 1 +#define CONFIG_SCSI_DC390T_MODULE 1 +#undef CONFIG_SCSI_T128 +#undef CONFIG_SCSI_U14_34F +#undef CONFIG_SCSI_ULTRASTOR +#undef CONFIG_SCSI_NSP32 +#undef CONFIG_SCSI_DEBUG /* - * IrDA options + * PCMCIA SCSI adapter support */ -#define CONFIG_IRDA_CACHE_LAST_LSAP 1 -#define CONFIG_IRDA_FAST_RR 1 -#undef CONFIG_IRDA_DEBUG +#define CONFIG_PCMCIA_AHA152X_MODULE 1 +#define CONFIG_PCMCIA_FDOMAIN_MODULE 1 +#define CONFIG_PCMCIA_NINJA_SCSI_MODULE 1 +#define CONFIG_PCMCIA_QLOGIC_MODULE 1 +#define CONFIG_PCMCIA_SYM53C500_MODULE 1 /* - * Infrared-port device drivers + * Old CD-ROM drivers (not SCSI, not IDE) */ +#undef CONFIG_CD_NO_IDESCSI /* - * SIR device drivers + * Multi-device support (RAID and LVM) */ -#define CONFIG_IRTTY_SIR_MODULE 1 +#define CONFIG_MD 1 +#define CONFIG_BLK_DEV_MD 1 +#define CONFIG_MD_LINEAR_MODULE 1 +#define CONFIG_MD_RAID0_MODULE 1 +#define CONFIG_MD_RAID1_MODULE 1 +#define CONFIG_MD_RAID10_MODULE 1 +#define CONFIG_MD_RAID5_MODULE 1 +#define CONFIG_MD_RAID5_RESHAPE 1 +#define CONFIG_MD_RAID6_MODULE 1 +#define CONFIG_MD_MULTIPATH_MODULE 1 +#define CONFIG_MD_FAULTY_MODULE 1 +#define CONFIG_BLK_DEV_DM_MODULE 1 +#define CONFIG_DM_CRYPT_MODULE 1 +#define CONFIG_DM_SNAPSHOT_MODULE 1 +#define CONFIG_DM_MIRROR_MODULE 1 +#define CONFIG_DM_ZERO_MODULE 1 +#define CONFIG_DM_MULTIPATH_MODULE 1 +#define CONFIG_DM_MULTIPATH_EMC_MODULE 1 /* - * Dongle support + * Fusion MPT device support */ -#define CONFIG_DONGLE 1 -#define CONFIG_ESI_DONGLE_MODULE 1 -#define CONFIG_ACTISYS_DONGLE_MODULE 1 -#define CONFIG_TEKRAM_DONGLE_MODULE 1 -#define CONFIG_LITELINK_DONGLE_MODULE 1 -#define CONFIG_MA600_DONGLE_MODULE 1 -#define CONFIG_GIRBIL_DONGLE_MODULE 1 -#define CONFIG_MCP2120_DONGLE_MODULE 1 -#define CONFIG_OLD_BELKIN_DONGLE_MODULE 1 -#define CONFIG_ACT200L_DONGLE_MODULE 1 +#define CONFIG_FUSION 1 +#define CONFIG_FUSION_SPI_MODULE 1 +#define CONFIG_FUSION_FC_MODULE 1 +#define CONFIG_FUSION_SAS_MODULE 1 +#define CONFIG_FUSION_MAX_SGE 40 +#define CONFIG_FUSION_CTL_MODULE 1 +#define CONFIG_FUSION_LAN_MODULE 1 /* - * Old SIR device drivers + * IEEE 1394 (FireWire) support */ +#define CONFIG_IEEE1394_MODULE 1 /* - * Old Serial dongle support + * Subsystem Options */ +#undef CONFIG_IEEE1394_VERBOSEDEBUG +#define CONFIG_IEEE1394_OUI_DB 1 +#define CONFIG_IEEE1394_EXTRA_CONFIG_ROMS 1 +#define CONFIG_IEEE1394_CONFIG_ROM_IP1394 1 +#undef CONFIG_IEEE1394_EXPORT_FULL_API /* - * FIR device drivers + * Device Drivers */ -#define CONFIG_USB_IRDA_MODULE 1 -#define CONFIG_SIGMATEL_FIR_MODULE 1 -#define CONFIG_NSC_FIR_MODULE 1 -#undef CONFIG_WINBOND_FIR -#undef CONFIG_TOSHIBA_FIR -#undef CONFIG_SMC_IRCC_FIR -#undef CONFIG_ALI_FIR -#undef CONFIG_VLSI_FIR -#undef CONFIG_VIA_FIR -#define CONFIG_BT_MODULE 1 -#define CONFIG_BT_L2CAP_MODULE 1 -#define CONFIG_BT_SCO_MODULE 1 -#define CONFIG_BT_RFCOMM_MODULE 1 -#define CONFIG_BT_RFCOMM_TTY 1 -#define CONFIG_BT_BNEP_MODULE 1 -#define CONFIG_BT_BNEP_MC_FILTER 1 -#define CONFIG_BT_BNEP_PROTO_FILTER 1 -#define CONFIG_BT_CMTP_MODULE 1 +#define CONFIG_IEEE1394_PCILYNX_MODULE 1 +#define CONFIG_IEEE1394_OHCI1394_MODULE 1 /* - * Bluetooth device drivers + * Protocol Drivers */ -#define CONFIG_BT_HCIUSB_MODULE 1 -#define CONFIG_BT_HCIUSB_SCO 1 -#define CONFIG_BT_HCIUART_MODULE 1 -#define CONFIG_BT_HCIUART_H4 1 -#define CONFIG_BT_HCIUART_BCSP 1 -#define CONFIG_BT_HCIUART_BCSP_TXCRC 1 -#define CONFIG_BT_HCIBCM203X_MODULE 1 -#define CONFIG_BT_HCIBFUSB_MODULE 1 -#define CONFIG_BT_HCIDTL1_MODULE 1 -#define CONFIG_BT_HCIBT3C_MODULE 1 -#define CONFIG_BT_HCIBLUECARD_MODULE 1 -#define CONFIG_BT_HCIBTUART_MODULE 1 -#define CONFIG_BT_HCIVHCI_MODULE 1 -#define CONFIG_TUX_MODULE 1 +#define CONFIG_IEEE1394_VIDEO1394_MODULE 1 +#define CONFIG_IEEE1394_SBP2_MODULE 1 +#undef CONFIG_IEEE1394_SBP2_PHYS_DMA +#define CONFIG_IEEE1394_ETH1394_MODULE 1 +#define CONFIG_IEEE1394_DV1394_MODULE 1 +#define CONFIG_IEEE1394_RAWIO_MODULE 1 /* - * TUX options + * I2O device support + */ +#define CONFIG_I2O_MODULE 1 +#undef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES +#define CONFIG_I2O_EXT_ADAPTEC 1 +#define CONFIG_I2O_CONFIG_MODULE 1 +#define CONFIG_I2O_CONFIG_OLD_IOCTL 1 +#define CONFIG_I2O_BUS_MODULE 1 +#define CONFIG_I2O_BLOCK_MODULE 1 +#define CONFIG_I2O_SCSI_MODULE 1 +#define CONFIG_I2O_PROC_MODULE 1 + +/* + * Network device support */ -#define CONFIG_TUX_EXTCGI 1 -#undef CONFIG_TUX_EXTENDED_LOG -#undef CONFIG_TUX_DEBUG #define CONFIG_NETDEVICES 1 #define CONFIG_DUMMY_MODULE 1 #define CONFIG_BONDING_MODULE 1 #define CONFIG_EQUALIZER_MODULE 1 #define CONFIG_TUN_MODULE 1 -#define CONFIG_ETHERTAP_MODULE 1 #define CONFIG_NET_SB1000_MODULE 1 /* @@ -1028,6 +1328,20 @@ */ #undef CONFIG_ARCNET +/* + * PHY device support + */ +#define CONFIG_PHYLIB_MODULE 1 + +/* + * MII PHY device drivers + */ +#define CONFIG_MARVELL_PHY_MODULE 1 +#define CONFIG_DAVICOM_PHY_MODULE 1 +#define CONFIG_QSEMI_PHY_MODULE 1 +#define CONFIG_LXT_PHY_MODULE 1 +#define CONFIG_CICADA_PHY_MODULE 1 + /* * Ethernet (10 or 100Mbit) */ @@ -1035,23 +1349,22 @@ #define CONFIG_MII_MODULE 1 #define CONFIG_HAPPYMEAL_MODULE 1 #define CONFIG_SUNGEM_MODULE 1 +#define CONFIG_CASSINI_MODULE 1 #define CONFIG_NET_VENDOR_3COM 1 -#define CONFIG_EL1_MODULE 1 -#define CONFIG_EL2_MODULE 1 -#define CONFIG_ELPLUS_MODULE 1 -#define CONFIG_EL16_MODULE 1 +#undef CONFIG_EL1 +#undef CONFIG_EL2 +#undef CONFIG_ELPLUS +#undef CONFIG_EL16 #define CONFIG_EL3_MODULE 1 -#define CONFIG_3C515_MODULE 1 +#undef CONFIG_3C515 #define CONFIG_VORTEX_MODULE 1 #define CONFIG_TYPHOON_MODULE 1 -#define CONFIG_LANCE_MODULE 1 +#undef CONFIG_LANCE #define CONFIG_NET_VENDOR_SMC 1 -#define CONFIG_WD80x3_MODULE 1 +#undef CONFIG_WD80x3 #define CONFIG_ULTRA_MODULE 1 -#define CONFIG_SMC9194_MODULE 1 -#define CONFIG_NET_VENDOR_RACAL 1 -#define CONFIG_NI52_MODULE 1 -#define CONFIG_NI65_MODULE 1 +#undef CONFIG_SMC9194 +#undef CONFIG_NET_VENDOR_RACAL /* * Tulip family network device support @@ -1065,34 +1378,44 @@ #define CONFIG_DE4X5_MODULE 1 #define CONFIG_WINBOND_840_MODULE 1 #define CONFIG_DM9102_MODULE 1 +#define CONFIG_ULI526X_MODULE 1 #define CONFIG_PCMCIA_XIRCOM_MODULE 1 +#undef CONFIG_PCMCIA_XIRTULIP #undef CONFIG_AT1700 -#define CONFIG_DEPCA_MODULE 1 +#undef CONFIG_DEPCA #define CONFIG_HP100_MODULE 1 -#undef CONFIG_NET_ISA +#define CONFIG_NET_ISA 1 +#undef CONFIG_E2100 +#define CONFIG_EWRK3_MODULE 1 +#undef CONFIG_EEXPRESS +#undef CONFIG_EEXPRESS_PRO +#undef CONFIG_HPLAN_PLUS +#undef CONFIG_HPLAN +#undef CONFIG_LP486E +#undef CONFIG_ETH16I #define CONFIG_NE2000_MODULE 1 +#undef CONFIG_ZNET +#undef CONFIG_SEEQ8005 #define CONFIG_NET_PCI 1 #define CONFIG_PCNET32_MODULE 1 #define CONFIG_AMD8111_ETH_MODULE 1 #define CONFIG_AMD8111E_NAPI 1 #define CONFIG_ADAPTEC_STARFIRE_MODULE 1 #define CONFIG_ADAPTEC_STARFIRE_NAPI 1 -#define CONFIG_AC3200_MODULE 1 -#define CONFIG_APRICOT_MODULE 1 +#undef CONFIG_AC3200 +#undef CONFIG_APRICOT #define CONFIG_B44_MODULE 1 #define CONFIG_FORCEDETH_MODULE 1 -#define CONFIG_CS89x0_MODULE 1 +#undef CONFIG_CS89x0 #define CONFIG_DGRS_MODULE 1 -#define CONFIG_EEPRO100_MODULE 1 -#undef CONFIG_EEPRO100_PIO +#undef CONFIG_EEPRO100 #define CONFIG_E100_MODULE 1 -#define CONFIG_E100_NAPI 1 #define CONFIG_FEALNX_MODULE 1 #define CONFIG_NATSEMI_MODULE 1 #define CONFIG_NE2K_PCI_MODULE 1 #define CONFIG_8139CP_MODULE 1 #define CONFIG_8139TOO_MODULE 1 -#define CONFIG_8139TOO_PIO 1 +#undef CONFIG_8139TOO_PIO #undef CONFIG_8139TOO_TUNE_TWISTER #define CONFIG_8139TOO_8129 1 #undef CONFIG_8139_OLD_RX_RESET @@ -1109,20 +1432,32 @@ #define CONFIG_DE620_MODULE 1 /* - * Gigabit Ethernet (1000/10000 Mbit) + * Ethernet (1000 Mbit) */ -#define CONFIG_NET_GIGE 1 #define CONFIG_ACENIC_MODULE 1 #undef CONFIG_ACENIC_OMIT_TIGON_I #define CONFIG_DL2K_MODULE 1 #define CONFIG_E1000_MODULE 1 #define CONFIG_E1000_NAPI 1 +#undef CONFIG_E1000_DISABLE_PACKET_SPLIT #define CONFIG_NS83820_MODULE 1 #define CONFIG_HAMACHI_MODULE 1 #define CONFIG_YELLOWFIN_MODULE 1 #define CONFIG_R8169_MODULE 1 -#define CONFIG_SK98LIN_MODULE 1 +#define CONFIG_R8169_NAPI 1 +#define CONFIG_R8169_VLAN 1 +#define CONFIG_SIS190_MODULE 1 +#define CONFIG_SKGE_MODULE 1 +#define CONFIG_SKY2_MODULE 1 +#undef CONFIG_SK98LIN +#define CONFIG_VIA_VELOCITY_MODULE 1 #define CONFIG_TIGON3_MODULE 1 +#define CONFIG_BNX2_MODULE 1 + +/* + * Ethernet (10000 Mbit) + */ +#define CONFIG_CHELSIO_T1_MODULE 1 #define CONFIG_IXGB_MODULE 1 #define CONFIG_IXGB_NAPI 1 #define CONFIG_S2IO_MODULE 1 @@ -1131,19 +1466,26 @@ /* * Token Ring devices */ -#undef CONFIG_TR +#define CONFIG_TR 1 +#undef CONFIG_IBMTR +#define CONFIG_IBMOL_MODULE 1 +#define CONFIG_IBMLS_MODULE 1 +#define CONFIG_3C359_MODULE 1 +#undef CONFIG_TMS380TR +#undef CONFIG_SMCTR /* * Wireless LAN (non-hamradio) */ #define CONFIG_NET_RADIO 1 +#define CONFIG_NET_WIRELESS_RTNETLINK 1 /* * Obsolete Wireless cards support (pre-802.11) */ #undef CONFIG_STRIP #undef CONFIG_ARLAN -#define CONFIG_WAVELAN_MODULE 1 +#undef CONFIG_WAVELAN #define CONFIG_PCMCIA_WAVELAN_MODULE 1 #define CONFIG_PCMCIA_NETWAVE_MODULE 1 @@ -1155,10 +1497,18 @@ /* * Wireless 802.11b ISA/PCI cards support */ +#define CONFIG_IPW2100_MODULE 1 +#define CONFIG_IPW2100_MONITOR 1 +#undef CONFIG_IPW2100_DEBUG +#define CONFIG_IPW2200_MODULE 1 +#define CONFIG_IPW2200_MONITOR 1 +#define CONFIG_IPW_QOS 1 +#undef CONFIG_IPW2200_DEBUG #define CONFIG_AIRO_MODULE 1 #define CONFIG_HERMES_MODULE 1 #define CONFIG_PLX_HERMES_MODULE 1 #define CONFIG_TMD_HERMES_MODULE 1 +#define CONFIG_NORTEL_HERMES_MODULE 1 #define CONFIG_PCI_HERMES_MODULE 1 #define CONFIG_ATMEL_MODULE 1 #define CONFIG_PCI_ATMEL_MODULE 1 @@ -1167,6 +1517,7 @@ * Wireless 802.11b Pcmcia/Cardbus cards support */ #define CONFIG_PCMCIA_HERMES_MODULE 1 +#define CONFIG_PCMCIA_SPECTRUM_MODULE 1 #define CONFIG_AIRO_CS_MODULE 1 #define CONFIG_PCMCIA_ATMEL_MODULE 1 #define CONFIG_PCMCIA_WL3501_MODULE 1 @@ -1175,6 +1526,19 @@ * Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support */ #define CONFIG_PRISM54_MODULE 1 +#define CONFIG_HOSTAP_MODULE 1 +#define CONFIG_HOSTAP_FIRMWARE 1 +#define CONFIG_HOSTAP_FIRMWARE_NVRAM 1 +#define CONFIG_HOSTAP_PLX_MODULE 1 +#define CONFIG_HOSTAP_PCI_MODULE 1 +#define CONFIG_HOSTAP_CS_MODULE 1 +#define CONFIG_BCM43XX_MODULE 1 +#define CONFIG_BCM43XX_DEBUG 1 +#define CONFIG_BCM43XX_DMA 1 +#define CONFIG_BCM43XX_PIO 1 +#define CONFIG_BCM43XX_DMA_AND_PIO_MODE 1 +#undef CONFIG_BCM43XX_DMA_MODE +#undef CONFIG_BCM43XX_PIO_MODE #define CONFIG_NET_WIRELESS 1 /* @@ -1189,11 +1553,40 @@ #define CONFIG_PCMCIA_SMC91C92_MODULE 1 #define CONFIG_PCMCIA_XIRC2PS_MODULE 1 #define CONFIG_PCMCIA_AXNET_MODULE 1 +#define CONFIG_PCMCIA_IBMTR_MODULE 1 /* * Wan interfaces */ #undef CONFIG_WAN + +/* + * ATM drivers + */ +#undef CONFIG_ATM_DUMMY +#define CONFIG_ATM_TCP_MODULE 1 +#define CONFIG_ATM_LANAI_MODULE 1 +#define CONFIG_ATM_ENI_MODULE 1 +#undef CONFIG_ATM_ENI_DEBUG +#undef CONFIG_ATM_ENI_TUNE_BURST +#define CONFIG_ATM_FIRESTREAM_MODULE 1 +#undef CONFIG_ATM_ZATM +#define CONFIG_ATM_NICSTAR_MODULE 1 +#undef CONFIG_ATM_NICSTAR_USE_SUNI +#undef CONFIG_ATM_NICSTAR_USE_IDT77105 +#define CONFIG_ATM_IDT77252_MODULE 1 +#undef CONFIG_ATM_IDT77252_DEBUG +#undef CONFIG_ATM_IDT77252_RCV_ALL +#define CONFIG_ATM_IDT77252_USE_SUNI 1 +#define CONFIG_ATM_AMBASSADOR_MODULE 1 +#undef CONFIG_ATM_AMBASSADOR_DEBUG +#define CONFIG_ATM_HORIZON_MODULE 1 +#undef CONFIG_ATM_HORIZON_DEBUG +#undef CONFIG_ATM_IA +#define CONFIG_ATM_FORE200E_MAYBE_MODULE 1 +#undef CONFIG_ATM_FORE200E_PCA +#define CONFIG_ATM_HE_MODULE 1 +#undef CONFIG_ATM_HE_USE_SUNI #define CONFIG_FDDI 1 #undef CONFIG_DEFXX #define CONFIG_SKFP_MODULE 1 @@ -1206,11 +1599,20 @@ #define CONFIG_PPP_SYNC_TTY_MODULE 1 #define CONFIG_PPP_DEFLATE_MODULE 1 #undef CONFIG_PPP_BSDCOMP +#define CONFIG_PPP_MPPE_MODULE 1 #define CONFIG_PPPOE_MODULE 1 -#undef CONFIG_SLIP +#define CONFIG_PPPOATM_MODULE 1 +#define CONFIG_SLIP_MODULE 1 +#define CONFIG_SLIP_COMPRESSED 1 +#define CONFIG_SLIP_SMART 1 +#undef CONFIG_SLIP_MODE_SLIP6 #define CONFIG_NET_FC 1 #undef CONFIG_SHAPER #define CONFIG_NETCONSOLE_MODULE 1 +#define CONFIG_NETPOLL 1 +#undef CONFIG_NETPOLL_RX +#define CONFIG_NETPOLL_TRAP 1 +#define CONFIG_NET_POLL_CONTROLLER 1 /* * ISDN subsystem @@ -1232,6 +1634,8 @@ /* * ISDN feature submodules */ +#define CONFIG_ISDN_DRV_LOOP_MODULE 1 +#define CONFIG_ISDN_DIVERSION_MODULE 1 /* * ISDN4Linux hardware drivers @@ -1257,27 +1661,27 @@ /* * HiSax supported cards */ -#define CONFIG_HISAX_16_0 1 +#undef CONFIG_HISAX_16_0 #define CONFIG_HISAX_16_3 1 #define CONFIG_HISAX_TELESPCI 1 #define CONFIG_HISAX_S0BOX 1 -#define CONFIG_HISAX_AVM_A1 1 +#undef CONFIG_HISAX_AVM_A1 #define CONFIG_HISAX_FRITZPCI 1 #define CONFIG_HISAX_AVM_A1_PCMCIA 1 #define CONFIG_HISAX_ELSA 1 -#define CONFIG_HISAX_IX1MICROR2 1 +#undef CONFIG_HISAX_IX1MICROR2 #define CONFIG_HISAX_DIEHLDIVA 1 -#define CONFIG_HISAX_ASUSCOM 1 -#define CONFIG_HISAX_TELEINT 1 -#define CONFIG_HISAX_HFCS 1 +#undef CONFIG_HISAX_ASUSCOM +#undef CONFIG_HISAX_TELEINT +#undef CONFIG_HISAX_HFCS #define CONFIG_HISAX_SEDLBAUER 1 -#define CONFIG_HISAX_SPORTSTER 1 -#define CONFIG_HISAX_MIC 1 +#undef CONFIG_HISAX_SPORTSTER +#undef CONFIG_HISAX_MIC #define CONFIG_HISAX_NETJET 1 #define CONFIG_HISAX_NETJET_U 1 #define CONFIG_HISAX_NICCY 1 -#define CONFIG_HISAX_ISURF 1 -#define CONFIG_HISAX_HSTSAPHIR 1 +#undef CONFIG_HISAX_ISURF +#undef CONFIG_HISAX_HSTSAPHIR #define CONFIG_HISAX_BKM_A4T 1 #define CONFIG_HISAX_SCT_QUADRO 1 #define CONFIG_HISAX_GAZEL 1 @@ -1299,18 +1703,29 @@ * HiSax sub driver modules */ #define CONFIG_HISAX_ST5481_MODULE 1 -#define CONFIG_HISAX_HFCUSB_MODULE 1 +#undef CONFIG_HISAX_HFCUSB +#define CONFIG_HISAX_HFC4S8S_MODULE 1 #define CONFIG_HISAX_FRITZ_PCIPNP_MODULE 1 #define CONFIG_HISAX_HDLC 1 /* * Active cards */ -#define CONFIG_ISDN_DRV_ICN_MODULE 1 -#define CONFIG_ISDN_DRV_PCBIT_MODULE 1 -#define CONFIG_ISDN_DRV_SC_MODULE 1 -#define CONFIG_ISDN_DRV_ACT2000_MODULE 1 -#define CONFIG_ISDN_DRV_TPAM_MODULE 1 +#undef CONFIG_ISDN_DRV_ICN +#undef CONFIG_ISDN_DRV_PCBIT +#undef CONFIG_ISDN_DRV_SC +#undef CONFIG_ISDN_DRV_ACT2000 +#define CONFIG_HYSDN_MODULE 1 +#define CONFIG_HYSDN_CAPI 1 + +/* + * Siemens Gigaset + */ +#define CONFIG_ISDN_DRV_GIGASET_MODULE 1 +#define CONFIG_GIGASET_BASE_MODULE 1 +#define CONFIG_GIGASET_M105_MODULE 1 +#undef CONFIG_GIGASET_DEBUG +#undef CONFIG_GIGASET_UNDOCREQ /* * CAPI subsystem @@ -1331,6 +1746,14 @@ * Active AVM cards */ #define CONFIG_CAPI_AVM 1 +#undef CONFIG_ISDN_DRV_AVMB1_B1ISA +#define CONFIG_ISDN_DRV_AVMB1_B1PCI_MODULE 1 +#define CONFIG_ISDN_DRV_AVMB1_B1PCIV4 1 +#undef CONFIG_ISDN_DRV_AVMB1_T1ISA +#define CONFIG_ISDN_DRV_AVMB1_B1PCMCIA_MODULE 1 +#define CONFIG_ISDN_DRV_AVMB1_AVM_CS_MODULE 1 +#define CONFIG_ISDN_DRV_AVMB1_T1PCI_MODULE 1 +#define CONFIG_ISDN_DRV_AVMB1_C4_MODULE 1 /* * Active Eicon DIVA Server cards @@ -1365,24 +1788,6 @@ #define CONFIG_INPUT_EVDEV 1 #undef CONFIG_INPUT_EVBUG -/* - * Input I/O drivers - */ -#define CONFIG_GAMEPORT_MODULE 1 -#define CONFIG_SOUND_GAMEPORT_MODULE 1 -#define CONFIG_GAMEPORT_NS558_MODULE 1 -#define CONFIG_GAMEPORT_L4_MODULE 1 -#define CONFIG_GAMEPORT_EMU10K1_MODULE 1 -#define CONFIG_GAMEPORT_VORTEX_MODULE 1 -#define CONFIG_GAMEPORT_FM801_MODULE 1 -#define CONFIG_GAMEPORT_CS461x_MODULE 1 -#define CONFIG_SERIO 1 -#define CONFIG_SERIO_I8042 1 -#define CONFIG_SERIO_SERPORT 1 -#undef CONFIG_SERIO_CT82C710 -#undef CONFIG_SERIO_PARKBD -#undef CONFIG_SERIO_PCIPS2 - /* * Input Device Drivers */ @@ -1395,10 +1800,9 @@ #define CONFIG_INPUT_MOUSE 1 #define CONFIG_MOUSE_PS2 1 #define CONFIG_MOUSE_SERIAL_MODULE 1 -#define CONFIG_MOUSE_INPORT_MODULE 1 -#define CONFIG_MOUSE_ATIXL 1 -#define CONFIG_MOUSE_LOGIBM_MODULE 1 -#define CONFIG_MOUSE_PC110PAD_MODULE 1 +#undef CONFIG_MOUSE_INPORT +#undef CONFIG_MOUSE_LOGIBM +#undef CONFIG_MOUSE_PC110PAD #define CONFIG_MOUSE_VSXXXAA_MODULE 1 #define CONFIG_INPUT_JOYSTICK 1 #define CONFIG_JOYSTICK_ANALOG_MODULE 1 @@ -1420,16 +1824,37 @@ #define CONFIG_JOYSTICK_SPACEORB_MODULE 1 #define CONFIG_JOYSTICK_SPACEBALL_MODULE 1 #define CONFIG_JOYSTICK_STINGER_MODULE 1 -#define CONFIG_JOYSTICK_TWIDDLER_MODULE 1 +#define CONFIG_JOYSTICK_TWIDJOY_MODULE 1 #define CONFIG_JOYSTICK_DB9_MODULE 1 #define CONFIG_JOYSTICK_GAMECON_MODULE 1 #define CONFIG_JOYSTICK_TURBOGRAFX_MODULE 1 -#undef CONFIG_INPUT_JOYDUMP +#define CONFIG_JOYSTICK_JOYDUMP_MODULE 1 #define CONFIG_INPUT_TOUCHSCREEN 1 #define CONFIG_TOUCHSCREEN_GUNZE_MODULE 1 +#define CONFIG_TOUCHSCREEN_ELO_MODULE 1 +#define CONFIG_TOUCHSCREEN_MTOUCH_MODULE 1 +#define CONFIG_TOUCHSCREEN_MK712_MODULE 1 #define CONFIG_INPUT_MISC 1 #define CONFIG_INPUT_PCSPKR_MODULE 1 -#undef CONFIG_INPUT_UINPUT +#define CONFIG_INPUT_WISTRON_BTNS_MODULE 1 +#define CONFIG_INPUT_UINPUT_MODULE 1 + +/* + * Hardware I/O ports + */ +#define CONFIG_SERIO 1 +#define CONFIG_SERIO_I8042 1 +#define CONFIG_SERIO_SERPORT 1 +#undef CONFIG_SERIO_CT82C710 +#undef CONFIG_SERIO_PARKBD +#undef CONFIG_SERIO_PCIPS2 +#define CONFIG_SERIO_LIBPS2 1 +#define CONFIG_SERIO_RAW_MODULE 1 +#define CONFIG_GAMEPORT_MODULE 1 +#define CONFIG_GAMEPORT_NS558_MODULE 1 +#define CONFIG_GAMEPORT_L4_MODULE 1 +#define CONFIG_GAMEPORT_EMU10K1_MODULE 1 +#define CONFIG_GAMEPORT_FM801_MODULE 1 /* * Character devices @@ -1438,33 +1863,50 @@ #define CONFIG_VT_CONSOLE 1 #define CONFIG_HW_CONSOLE 1 #define CONFIG_SERIAL_NONSTANDARD 1 +#undef CONFIG_COMPUTONE #define CONFIG_ROCKETPORT_MODULE 1 #undef CONFIG_CYCLADES +#undef CONFIG_DIGIEPCA +#undef CONFIG_ESPSERIAL +#undef CONFIG_MOXA_INTELLIO +#undef CONFIG_MOXA_SMARTIO +#undef CONFIG_ISI #define CONFIG_SYNCLINK_MODULE 1 #define CONFIG_SYNCLINKMP_MODULE 1 +#undef CONFIG_SYNCLINK_GT #define CONFIG_N_HDLC_MODULE 1 -#define CONFIG_STALDRV 1 +#undef CONFIG_RISCOM8 +#undef CONFIG_SPECIALIX +#undef CONFIG_SX +#undef CONFIG_RIO +#undef CONFIG_STALDRV /* * Serial drivers */ #define CONFIG_SERIAL_8250 1 #define CONFIG_SERIAL_8250_CONSOLE 1 +#define CONFIG_SERIAL_8250_PCI 1 +#define CONFIG_SERIAL_8250_PNP 1 #define CONFIG_SERIAL_8250_CS_MODULE 1 -#undef CONFIG_SERIAL_8250_ACPI -#define CONFIG_SERIAL_8250_NR_UARTS 4 +#define CONFIG_SERIAL_8250_NR_UARTS 32 +#define CONFIG_SERIAL_8250_RUNTIME_UARTS 4 #define CONFIG_SERIAL_8250_EXTENDED 1 -#undef CONFIG_SERIAL_8250_MANY_PORTS +#define CONFIG_SERIAL_8250_MANY_PORTS 1 #define CONFIG_SERIAL_8250_SHARE_IRQ 1 #define CONFIG_SERIAL_8250_DETECT_IRQ 1 -#define CONFIG_SERIAL_8250_MULTIPORT 1 #define CONFIG_SERIAL_8250_RSA 1 +#undef CONFIG_SERIAL_8250_FOURPORT +#undef CONFIG_SERIAL_8250_ACCENT +#undef CONFIG_SERIAL_8250_BOCA +#undef CONFIG_SERIAL_8250_HUB6 /* * Non-8250 serial port support */ #define CONFIG_SERIAL_CORE 1 #define CONFIG_SERIAL_CORE_CONSOLE 1 +#undef CONFIG_SERIAL_JSM #define CONFIG_UNIX98_PTYS 1 #undef CONFIG_LEGACY_PTYS #define CONFIG_CRASH_MODULE 1 @@ -1472,7 +1914,6 @@ #define CONFIG_LP_CONSOLE 1 #define CONFIG_PPDEV_MODULE 1 #define CONFIG_TIPAR_MODULE 1 -#undef CONFIG_QIC02_TAPE /* * IPMI @@ -1482,6 +1923,7 @@ #define CONFIG_IPMI_DEVICE_INTERFACE_MODULE 1 #define CONFIG_IPMI_SI_MODULE 1 #define CONFIG_IPMI_WATCHDOG_MODULE 1 +#define CONFIG_IPMI_POWEROFF_MODULE 1 /* * Watchdog Cards @@ -1493,30 +1935,33 @@ * Watchdog Device Drivers */ #define CONFIG_SOFT_WATCHDOG_MODULE 1 -#define CONFIG_ACQUIRE_WDT_MODULE 1 -#define CONFIG_ADVANTECH_WDT_MODULE 1 +#undef CONFIG_ACQUIRE_WDT +#undef CONFIG_ADVANTECH_WDT #define CONFIG_ALIM1535_WDT_MODULE 1 #define CONFIG_ALIM7101_WDT_MODULE 1 -#define CONFIG_SC520_WDT_MODULE 1 -#define CONFIG_EUROTECH_WDT_MODULE 1 -#define CONFIG_IB700_WDT_MODULE 1 -#define CONFIG_WAFER_WDT_MODULE 1 +#undef CONFIG_SC520_WDT +#undef CONFIG_EUROTECH_WDT +#undef CONFIG_IB700_WDT +#define CONFIG_IBMASR_MODULE 1 +#undef CONFIG_WAFER_WDT +#define CONFIG_I6300ESB_WDT_MODULE 1 #define CONFIG_I8XX_TCO_MODULE 1 -#define CONFIG_SC1200_WDT_MODULE 1 -#undef CONFIG_SCx200_WDT +#undef CONFIG_SC1200_WDT #undef CONFIG_60XX_WDT -#define CONFIG_CPU5_WDT_MODULE 1 +#undef CONFIG_SBC8360_WDT +#undef CONFIG_CPU5_WDT #define CONFIG_W83627HF_WDT_MODULE 1 #define CONFIG_W83877F_WDT_MODULE 1 +#define CONFIG_W83977F_WDT_MODULE 1 #define CONFIG_MACHZ_WDT_MODULE 1 +#undef CONFIG_SBC_EPX_C3_WATCHDOG /* * ISA-based Watchdog Cards */ -#define CONFIG_PCWATCHDOG_MODULE 1 +#undef CONFIG_PCWATCHDOG #undef CONFIG_MIXCOMWD -#define CONFIG_WDT_MODULE 1 -#undef CONFIG_WDT_501 +#undef CONFIG_WDT /* * PCI-based Watchdog Cards @@ -1530,7 +1975,7 @@ */ #define CONFIG_USBPCWATCHDOG_MODULE 1 #define CONFIG_HW_RANDOM_MODULE 1 -#define CONFIG_NVRAM_MODULE 1 +#define CONFIG_NVRAM 1 #define CONFIG_RTC 1 #define CONFIG_DTLK_MODULE 1 #define CONFIG_R3964_MODULE 1 @@ -1540,36 +1985,50 @@ /* * Ftape, the floppy tape device driver */ +#undef CONFIG_FTAPE #define CONFIG_AGP 1 #define CONFIG_AGP_ALI 1 #define CONFIG_AGP_ATI 1 #define CONFIG_AGP_AMD 1 #define CONFIG_AGP_AMD64 1 #define CONFIG_AGP_INTEL 1 -#define CONFIG_AGP_INTEL_MCH 1 #define CONFIG_AGP_NVIDIA 1 #define CONFIG_AGP_SIS 1 #define CONFIG_AGP_SWORKS 1 #define CONFIG_AGP_VIA 1 #define CONFIG_AGP_EFFICEON 1 -#define CONFIG_DRM 1 +#define CONFIG_DRM_MODULE 1 #define CONFIG_DRM_TDFX_MODULE 1 -#define CONFIG_DRM_GAMMA_MODULE 1 #define CONFIG_DRM_R128_MODULE 1 #define CONFIG_DRM_RADEON_MODULE 1 #define CONFIG_DRM_I810_MODULE 1 #define CONFIG_DRM_I830_MODULE 1 +#define CONFIG_DRM_I915_MODULE 1 #define CONFIG_DRM_MGA_MODULE 1 #define CONFIG_DRM_SIS_MODULE 1 +#define CONFIG_DRM_VIA_MODULE 1 +#define CONFIG_DRM_SAVAGE_MODULE 1 /* * PCMCIA character devices */ #define CONFIG_SYNCLINK_CS_MODULE 1 +#define CONFIG_CARDMAN_4000_MODULE 1 +#define CONFIG_CARDMAN_4040_MODULE 1 #define CONFIG_MWAVE_MODULE 1 +#define CONFIG_CS5535_GPIO_MODULE 1 #undef CONFIG_RAW_DRIVER +#define CONFIG_HPET 1 +#undef CONFIG_HPET_RTC_IRQ +#undef CONFIG_HPET_MMAP #define CONFIG_HANGCHECK_TIMER_MODULE 1 +/* + * TPM devices + */ +#undef CONFIG_TCG_TPM +#undef CONFIG_TELCLOCK + /* * I2C support */ @@ -1581,6 +2040,7 @@ */ #define CONFIG_I2C_ALGOBIT_MODULE 1 #define CONFIG_I2C_ALGOPCF_MODULE 1 +#define CONFIG_I2C_ALGOPCA_MODULE 1 /* * I2C Hardware Bus support @@ -1589,57 +2049,112 @@ #define CONFIG_I2C_ALI1563_MODULE 1 #define CONFIG_I2C_ALI15X3_MODULE 1 #define CONFIG_I2C_AMD756_MODULE 1 +#define CONFIG_I2C_AMD756_S4882_MODULE 1 #define CONFIG_I2C_AMD8111_MODULE 1 +#undef CONFIG_I2C_ELEKTOR #define CONFIG_I2C_I801_MODULE 1 #define CONFIG_I2C_I810_MODULE 1 +#define CONFIG_I2C_PIIX4_MODULE 1 #define CONFIG_I2C_ISA_MODULE 1 #define CONFIG_I2C_NFORCE2_MODULE 1 -#undef CONFIG_I2C_PARPORT -#undef CONFIG_I2C_PARPORT_LIGHT -#define CONFIG_I2C_PIIX4_MODULE 1 +#define CONFIG_I2C_PARPORT_MODULE 1 +#define CONFIG_I2C_PARPORT_LIGHT_MODULE 1 #define CONFIG_I2C_PROSAVAGE_MODULE 1 #define CONFIG_I2C_SAVAGE4_MODULE 1 #undef CONFIG_SCx200_ACB #define CONFIG_I2C_SIS5595_MODULE 1 #define CONFIG_I2C_SIS630_MODULE 1 #define CONFIG_I2C_SIS96X_MODULE 1 +#define CONFIG_I2C_STUB_MODULE 1 #define CONFIG_I2C_VIA_MODULE 1 #define CONFIG_I2C_VIAPRO_MODULE 1 #define CONFIG_I2C_VOODOO3_MODULE 1 +#define CONFIG_I2C_PCA_ISA_MODULE 1 + +/* + * Miscellaneous I2C Chip support + */ +#define CONFIG_SENSORS_DS1337_MODULE 1 +#define CONFIG_SENSORS_DS1374_MODULE 1 +#define CONFIG_SENSORS_EEPROM_MODULE 1 +#define CONFIG_SENSORS_PCF8574_MODULE 1 +#define CONFIG_SENSORS_PCA9539_MODULE 1 +#define CONFIG_SENSORS_PCF8591_MODULE 1 +#define CONFIG_SENSORS_MAX6875_MODULE 1 +#undef CONFIG_I2C_DEBUG_CORE +#undef CONFIG_I2C_DEBUG_ALGO +#undef CONFIG_I2C_DEBUG_BUS +#undef CONFIG_I2C_DEBUG_CHIP + +/* + * SPI support + */ +#undef CONFIG_SPI +#undef CONFIG_SPI_MASTER + +/* + * Dallas's 1-wire bus + */ +#define CONFIG_W1_MODULE 1 + +/* + * 1-wire Bus Masters + */ +#define CONFIG_W1_MASTER_MATROX_MODULE 1 +#define CONFIG_W1_MASTER_DS9490_MODULE 1 +#define CONFIG_W1_MASTER_DS9490_BRIDGE_MODULE 1 +#define CONFIG_W1_MASTER_DS2482_MODULE 1 + +/* + * 1-wire Slaves + */ +#define CONFIG_W1_SLAVE_THERM_MODULE 1 +#define CONFIG_W1_SLAVE_SMEM_MODULE 1 +#define CONFIG_W1_SLAVE_DS2433_MODULE 1 /* - * Hardware Sensors Chip support + * Hardware Monitoring support */ -#define CONFIG_I2C_SENSOR_MODULE 1 +#define CONFIG_HWMON_MODULE 1 +#define CONFIG_HWMON_VID_MODULE 1 #define CONFIG_SENSORS_ADM1021_MODULE 1 +#define CONFIG_SENSORS_ADM1025_MODULE 1 +#define CONFIG_SENSORS_ADM1026_MODULE 1 +#define CONFIG_SENSORS_ADM1031_MODULE 1 +#define CONFIG_SENSORS_ADM9240_MODULE 1 #define CONFIG_SENSORS_ASB100_MODULE 1 +#define CONFIG_SENSORS_ATXP1_MODULE 1 #define CONFIG_SENSORS_DS1621_MODULE 1 +#define CONFIG_SENSORS_F71805F_MODULE 1 #define CONFIG_SENSORS_FSCHER_MODULE 1 +#define CONFIG_SENSORS_FSCPOS_MODULE 1 #define CONFIG_SENSORS_GL518SM_MODULE 1 +#define CONFIG_SENSORS_GL520SM_MODULE 1 #define CONFIG_SENSORS_IT87_MODULE 1 +#define CONFIG_SENSORS_LM63_MODULE 1 #define CONFIG_SENSORS_LM75_MODULE 1 +#define CONFIG_SENSORS_LM77_MODULE 1 #define CONFIG_SENSORS_LM78_MODULE 1 #define CONFIG_SENSORS_LM80_MODULE 1 #define CONFIG_SENSORS_LM83_MODULE 1 #define CONFIG_SENSORS_LM85_MODULE 1 +#define CONFIG_SENSORS_LM87_MODULE 1 #define CONFIG_SENSORS_LM90_MODULE 1 +#define CONFIG_SENSORS_LM92_MODULE 1 #define CONFIG_SENSORS_MAX1619_MODULE 1 +#define CONFIG_SENSORS_PC87360_MODULE 1 +#define CONFIG_SENSORS_SIS5595_MODULE 1 +#define CONFIG_SENSORS_SMSC47M1_MODULE 1 +#define CONFIG_SENSORS_SMSC47B397_MODULE 1 #define CONFIG_SENSORS_VIA686A_MODULE 1 +#define CONFIG_SENSORS_VT8231_MODULE 1 #define CONFIG_SENSORS_W83781D_MODULE 1 +#define CONFIG_SENSORS_W83792D_MODULE 1 #define CONFIG_SENSORS_W83L785TS_MODULE 1 #define CONFIG_SENSORS_W83627HF_MODULE 1 - -/* - * Other I2C Chip support - */ -#define CONFIG_SENSORS_EEPROM_MODULE 1 -#define CONFIG_SENSORS_PCF8574_MODULE 1 -#define CONFIG_SENSORS_PCF8591_MODULE 1 -#define CONFIG_SENSORS_RTC8564_MODULE 1 -#undef CONFIG_I2C_DEBUG_CORE -#undef CONFIG_I2C_DEBUG_ALGO -#undef CONFIG_I2C_DEBUG_BUS -#undef CONFIG_I2C_DEBUG_CHIP +#define CONFIG_SENSORS_W83627EHF_MODULE 1 +#define CONFIG_SENSORS_HDAPS_MODULE 1 +#undef CONFIG_HWMON_DEBUG_CHIP /* * Misc devices @@ -1650,22 +2165,30 @@ * Multimedia devices */ #define CONFIG_VIDEO_DEV_MODULE 1 +#define CONFIG_VIDEO_V4L1 1 +#define CONFIG_VIDEO_V4L1_COMPAT 1 +#define CONFIG_VIDEO_V4L2_MODULE 1 /* - * Video For Linux + * Video Capture Adapters */ /* - * Video Adapters + * Video Capture Adapters */ +#undef CONFIG_VIDEO_ADV_DEBUG +#undef CONFIG_VIDEO_VIVI #define CONFIG_VIDEO_BT848_MODULE 1 -#define CONFIG_VIDEO_PMS_MODULE 1 +#define CONFIG_VIDEO_BT848_DVB 1 +#define CONFIG_VIDEO_SAA6588_MODULE 1 +#undef CONFIG_VIDEO_PMS #define CONFIG_VIDEO_BWQCAM_MODULE 1 #define CONFIG_VIDEO_CQCAM_MODULE 1 #define CONFIG_VIDEO_W9966_MODULE 1 #define CONFIG_VIDEO_CPIA_MODULE 1 #define CONFIG_VIDEO_CPIA_PP_MODULE 1 #define CONFIG_VIDEO_CPIA_USB_MODULE 1 +#define CONFIG_VIDEO_CPIA2_MODULE 1 #define CONFIG_VIDEO_SAA5246A_MODULE 1 #define CONFIG_VIDEO_SAA5249_MODULE 1 #define CONFIG_TUNER_3036_MODULE 1 @@ -1676,95 +2199,262 @@ #define CONFIG_VIDEO_ZORAN_DC30_MODULE 1 #define CONFIG_VIDEO_ZORAN_LML33_MODULE 1 #define CONFIG_VIDEO_ZORAN_LML33R10_MODULE 1 +#define CONFIG_VIDEO_MEYE_MODULE 1 #define CONFIG_VIDEO_SAA7134_MODULE 1 +#define CONFIG_VIDEO_SAA7134_ALSA_MODULE 1 +#define CONFIG_VIDEO_SAA7134_DVB_MODULE 1 +#define CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS 1 #define CONFIG_VIDEO_MXB_MODULE 1 #define CONFIG_VIDEO_DPC_MODULE 1 #define CONFIG_VIDEO_HEXIUM_ORION_MODULE 1 #define CONFIG_VIDEO_HEXIUM_GEMINI_MODULE 1 +#define CONFIG_VIDEO_CX88_VP3054_MODULE 1 #define CONFIG_VIDEO_CX88_MODULE 1 +#define CONFIG_VIDEO_CX88_ALSA_MODULE 1 +#define CONFIG_VIDEO_CX88_DVB_MODULE 1 +#define CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS 1 +#define CONFIG_VIDEO_OVCAMCHIP_MODULE 1 + +/* + * Encoders and Decoders + */ +#define CONFIG_VIDEO_MSP3400_MODULE 1 +#define CONFIG_VIDEO_CS53L32A_MODULE 1 +#define CONFIG_VIDEO_WM8775_MODULE 1 +#define CONFIG_VIDEO_WM8739_MODULE 1 +#define CONFIG_VIDEO_CX25840_MODULE 1 +#define CONFIG_VIDEO_SAA711X_MODULE 1 +#define CONFIG_VIDEO_SAA7127_MODULE 1 +#define CONFIG_VIDEO_UPD64031A_MODULE 1 +#define CONFIG_VIDEO_UPD64083_MODULE 1 + +/* + * V4L USB devices + */ +#define CONFIG_VIDEO_EM28XX_MODULE 1 +#define CONFIG_USB_DSBR_MODULE 1 +#define CONFIG_VIDEO_USBVIDEO_MODULE 1 +#define CONFIG_USB_VICAM_MODULE 1 +#define CONFIG_USB_IBMCAM_MODULE 1 +#define CONFIG_USB_KONICAWC_MODULE 1 +#define CONFIG_USB_ET61X251_MODULE 1 +#define CONFIG_USB_OV511_MODULE 1 +#define CONFIG_USB_SE401_MODULE 1 +#define CONFIG_USB_SN9C102_MODULE 1 +#define CONFIG_USB_STV680_MODULE 1 +#define CONFIG_USB_W9968CF_MODULE 1 +#define CONFIG_USB_ZC0301_MODULE 1 +#define CONFIG_USB_PWC_MODULE 1 /* * Radio Adapters */ -#define CONFIG_RADIO_CADET_MODULE 1 -#define CONFIG_RADIO_RTRACK_MODULE 1 -#define CONFIG_RADIO_RTRACK2_MODULE 1 -#define CONFIG_RADIO_AZTECH_MODULE 1 -#define CONFIG_RADIO_GEMTEK_MODULE 1 +#undef CONFIG_RADIO_CADET +#undef CONFIG_RADIO_RTRACK +#undef CONFIG_RADIO_RTRACK2 +#undef CONFIG_RADIO_AZTECH +#undef CONFIG_RADIO_GEMTEK #define CONFIG_RADIO_GEMTEK_PCI_MODULE 1 #define CONFIG_RADIO_MAXIRADIO_MODULE 1 #define CONFIG_RADIO_MAESTRO_MODULE 1 -#define CONFIG_RADIO_SF16FMI_MODULE 1 -#define CONFIG_RADIO_SF16FMR2_MODULE 1 -#define CONFIG_RADIO_TERRATEC_MODULE 1 -#define CONFIG_RADIO_TRUST_MODULE 1 -#define CONFIG_RADIO_TYPHOON_MODULE 1 -#define CONFIG_RADIO_TYPHOON_PROC_FS 1 -#define CONFIG_RADIO_ZOLTRIX_MODULE 1 +#undef CONFIG_RADIO_SF16FMI +#undef CONFIG_RADIO_SF16FMR2 +#undef CONFIG_RADIO_TERRATEC +#undef CONFIG_RADIO_TRUST +#undef CONFIG_RADIO_TYPHOON +#undef CONFIG_RADIO_ZOLTRIX /* * Digital Video Broadcasting Devices */ -#undef CONFIG_DVB +#define CONFIG_DVB 1 +#define CONFIG_DVB_CORE_MODULE 1 + +/* + * Supported SAA7146 based PCI Adapters + */ +#define CONFIG_DVB_AV7110_MODULE 1 +#define CONFIG_DVB_AV7110_OSD 1 +#define CONFIG_DVB_BUDGET_MODULE 1 +#define CONFIG_DVB_BUDGET_CI_MODULE 1 +#define CONFIG_DVB_BUDGET_AV_MODULE 1 +#define CONFIG_DVB_BUDGET_PATCH_MODULE 1 + +/* + * Supported USB Adapters + */ +#define CONFIG_DVB_USB_MODULE 1 +#undef CONFIG_DVB_USB_DEBUG +#define CONFIG_DVB_USB_A800_MODULE 1 +#define CONFIG_DVB_USB_DIBUSB_MB_MODULE 1 +#undef CONFIG_DVB_USB_DIBUSB_MB_FAULTY +#define CONFIG_DVB_USB_DIBUSB_MC_MODULE 1 +#define CONFIG_DVB_USB_UMT_010_MODULE 1 +#define CONFIG_DVB_USB_CXUSB_MODULE 1 +#define CONFIG_DVB_USB_DIGITV_MODULE 1 +#define CONFIG_DVB_USB_VP7045_MODULE 1 +#define CONFIG_DVB_USB_VP702X_MODULE 1 +#define CONFIG_DVB_USB_NOVA_T_USB2_MODULE 1 +#define CONFIG_DVB_USB_DTT200U_MODULE 1 +#define CONFIG_DVB_TTUSB_BUDGET_MODULE 1 +#define CONFIG_DVB_TTUSB_DEC_MODULE 1 +#define CONFIG_DVB_CINERGYT2_MODULE 1 +#define CONFIG_DVB_CINERGYT2_TUNING 1 +#define CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT 32 +#define CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE 512 +#define CONFIG_DVB_CINERGYT2_QUERY_INTERVAL 250 +#define CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE 1 +#define CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL 100 + +/* + * Supported FlexCopII (B2C2) Adapters + */ +#define CONFIG_DVB_B2C2_FLEXCOP_MODULE 1 +#define CONFIG_DVB_B2C2_FLEXCOP_PCI_MODULE 1 +#define CONFIG_DVB_B2C2_FLEXCOP_USB_MODULE 1 +#undef CONFIG_DVB_B2C2_FLEXCOP_DEBUG + +/* + * Supported BT878 Adapters + */ +#define CONFIG_DVB_BT8XX_MODULE 1 + +/* + * Supported Pluto2 Adapters + */ +#define CONFIG_DVB_PLUTO2_MODULE 1 + +/* + * Supported DVB Frontends + */ + +/* + * Customise DVB Frontends + */ + +/* + * DVB-S (satellite) frontends + */ +#define CONFIG_DVB_STV0299_MODULE 1 +#define CONFIG_DVB_CX24110_MODULE 1 +#define CONFIG_DVB_CX24123_MODULE 1 +#define CONFIG_DVB_TDA8083_MODULE 1 +#define CONFIG_DVB_MT312_MODULE 1 +#define CONFIG_DVB_VES1X93_MODULE 1 +#define CONFIG_DVB_S5H1420_MODULE 1 + +/* + * DVB-T (terrestrial) frontends + */ +#define CONFIG_DVB_SP8870_MODULE 1 +#define CONFIG_DVB_SP887X_MODULE 1 +#define CONFIG_DVB_CX22700_MODULE 1 +#define CONFIG_DVB_CX22702_MODULE 1 +#define CONFIG_DVB_L64781_MODULE 1 +#define CONFIG_DVB_TDA1004X_MODULE 1 +#define CONFIG_DVB_NXT6000_MODULE 1 +#define CONFIG_DVB_MT352_MODULE 1 +#define CONFIG_DVB_ZL10353_MODULE 1 +#define CONFIG_DVB_DIB3000MB_MODULE 1 +#define CONFIG_DVB_DIB3000MC_MODULE 1 + +/* + * DVB-C (cable) frontends + */ +#define CONFIG_DVB_VES1820_MODULE 1 +#define CONFIG_DVB_TDA10021_MODULE 1 +#define CONFIG_DVB_STV0297_MODULE 1 + +/* + * ATSC (North American/Korean Terresterial DTV) frontends + */ +#define CONFIG_DVB_NXT200X_MODULE 1 +#define CONFIG_DVB_OR51211_MODULE 1 +#define CONFIG_DVB_OR51132_MODULE 1 +#define CONFIG_DVB_BCM3510_MODULE 1 +#define CONFIG_DVB_LGDT330X_MODULE 1 #define CONFIG_VIDEO_SAA7146_MODULE 1 #define CONFIG_VIDEO_SAA7146_VV_MODULE 1 #define CONFIG_VIDEO_VIDEOBUF_MODULE 1 #define CONFIG_VIDEO_TUNER_MODULE 1 #define CONFIG_VIDEO_BUF_MODULE 1 +#define CONFIG_VIDEO_BUF_DVB_MODULE 1 #define CONFIG_VIDEO_BTCX_MODULE 1 #define CONFIG_VIDEO_IR_MODULE 1 +#define CONFIG_VIDEO_TVEEPROM_MODULE 1 +#define CONFIG_USB_DABUSB_MODULE 1 /* * Graphics support */ #define CONFIG_FB 1 +#define CONFIG_FB_CFB_FILLRECT 1 +#define CONFIG_FB_CFB_COPYAREA 1 +#define CONFIG_FB_CFB_IMAGEBLIT 1 +#undef CONFIG_FB_MACMODES +#undef CONFIG_FB_FIRMWARE_EDID +#define CONFIG_FB_MODE_HELPERS 1 +#define CONFIG_FB_TILEBLITTING 1 +#define CONFIG_FB_CIRRUS_MODULE 1 #undef CONFIG_FB_PM2 #undef CONFIG_FB_CYBER2000 +#undef CONFIG_FB_ARC #undef CONFIG_FB_ASILIANT #undef CONFIG_FB_IMSTT #define CONFIG_FB_VGA16_MODULE 1 #define CONFIG_FB_VESA 1 #define CONFIG_VIDEO_SELECT 1 -#define CONFIG_FB_HGA_MODULE 1 -#define CONFIG_FB_HGA_ACCEL 1 +#undef CONFIG_FB_HGA +#undef CONFIG_FB_S1D13XXX +#undef CONFIG_FB_NVIDIA #define CONFIG_FB_RIVA_MODULE 1 +#undef CONFIG_FB_RIVA_I2C +#undef CONFIG_FB_RIVA_DEBUG #define CONFIG_FB_I810_MODULE 1 #define CONFIG_FB_I810_GTF 1 +#define CONFIG_FB_I810_I2C 1 +#define CONFIG_FB_INTEL_MODULE 1 +#undef CONFIG_FB_INTEL_DEBUG #define CONFIG_FB_MATROX_MODULE 1 #define CONFIG_FB_MATROX_MILLENIUM 1 #define CONFIG_FB_MATROX_MYSTIQUE 1 -#define CONFIG_FB_MATROX_G450 1 -#define CONFIG_FB_MATROX_G100 1 +#define CONFIG_FB_MATROX_G 1 #define CONFIG_FB_MATROX_I2C_MODULE 1 #define CONFIG_FB_MATROX_MAVEN_MODULE 1 #define CONFIG_FB_MATROX_MULTIHEAD 1 -#undef CONFIG_FB_RADEON_OLD #define CONFIG_FB_RADEON_MODULE 1 #define CONFIG_FB_RADEON_I2C 1 #undef CONFIG_FB_RADEON_DEBUG #define CONFIG_FB_ATY128_MODULE 1 #define CONFIG_FB_ATY_MODULE 1 #define CONFIG_FB_ATY_CT 1 +#define CONFIG_FB_ATY_GENERIC_LCD 1 #define CONFIG_FB_ATY_GX 1 -#undef CONFIG_FB_ATY_XL_INIT +#define CONFIG_FB_SAVAGE_MODULE 1 +#define CONFIG_FB_SAVAGE_I2C 1 +#define CONFIG_FB_SAVAGE_ACCEL 1 #undef CONFIG_FB_SIS #define CONFIG_FB_NEOMAGIC_MODULE 1 #define CONFIG_FB_KYRO_MODULE 1 #define CONFIG_FB_3DFX_MODULE 1 #define CONFIG_FB_3DFX_ACCEL 1 #define CONFIG_FB_VOODOO1_MODULE 1 +#define CONFIG_FB_CYBLA_MODULE 1 #define CONFIG_FB_TRIDENT_MODULE 1 #define CONFIG_FB_TRIDENT_ACCEL 1 +#undef CONFIG_FB_GEODE #undef CONFIG_FB_VIRTUAL /* * Console display driver support */ #define CONFIG_VGA_CONSOLE 1 -#define CONFIG_MDA_CONSOLE_MODULE 1 +#define CONFIG_VGACON_SOFT_SCROLLBACK 1 +#define CONFIG_VGACON_SOFT_SCROLLBACK_SIZE 64 +#undef CONFIG_MDA_CONSOLE #define CONFIG_DUMMY_CONSOLE 1 #define CONFIG_FRAMEBUFFER_CONSOLE 1 -#define CONFIG_PCI_CONSOLE 1 +#define CONFIG_FRAMEBUFFER_CONSOLE_ROTATION 1 #undef CONFIG_FONTS #define CONFIG_FONT_8x8 1 #define CONFIG_FONT_8x16 1 @@ -1776,6 +2466,11 @@ #undef CONFIG_LOGO_LINUX_MONO #undef CONFIG_LOGO_LINUX_VGA16 #define CONFIG_LOGO_LINUX_CLUT224 1 +#define CONFIG_BACKLIGHT_LCD_SUPPORT 1 +#define CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE 1 +#define CONFIG_BACKLIGHT_DEVICE 1 +#define CONFIG_LCD_CLASS_DEVICE_MODULE 1 +#define CONFIG_LCD_DEVICE 1 /* * Sound @@ -1795,8 +2490,13 @@ #define CONFIG_SND_OSSEMUL 1 #define CONFIG_SND_MIXER_OSS_MODULE 1 #define CONFIG_SND_PCM_OSS_MODULE 1 +#define CONFIG_SND_PCM_OSS_PLUGINS 1 #define CONFIG_SND_SEQUENCER_OSS 1 #define CONFIG_SND_RTCTIMER_MODULE 1 +#define CONFIG_SND_SEQ_RTCTIMER_DEFAULT 1 +#define CONFIG_SND_DYNAMIC_MINORS 1 +#undef CONFIG_SND_SUPPORT_OLD_API +#define CONFIG_SND_VERBOSE_PROCFS 1 #undef CONFIG_SND_VERBOSE_PRINTK #undef CONFIG_SND_DEBUG @@ -1807,6 +2507,8 @@ #define CONFIG_SND_OPL3_LIB_MODULE 1 #define CONFIG_SND_OPL4_LIB_MODULE 1 #define CONFIG_SND_VX_LIB_MODULE 1 +#define CONFIG_SND_AC97_CODEC_MODULE 1 +#define CONFIG_SND_AC97_BUS_MODULE 1 #define CONFIG_SND_DUMMY_MODULE 1 #define CONFIG_SND_VIRMIDI_MODULE 1 #define CONFIG_SND_MTPAV_MODULE 1 @@ -1816,87 +2518,102 @@ /* * ISA devices */ -#define CONFIG_SND_AD1816A_MODULE 1 -#define CONFIG_SND_AD1848_MODULE 1 -#define CONFIG_SND_CS4231_MODULE 1 -#define CONFIG_SND_CS4232_MODULE 1 +#define CONFIG_SND_CS4231_LIB_MODULE 1 +#define CONFIG_SND_ADLIB_MODULE 1 +#undef CONFIG_SND_AD1816A +#undef CONFIG_SND_AD1848 +#undef CONFIG_SND_ALS100 +#undef CONFIG_SND_AZT2320 +#undef CONFIG_SND_CMI8330 +#undef CONFIG_SND_CS4231 +#undef CONFIG_SND_CS4232 #define CONFIG_SND_CS4236_MODULE 1 -#define CONFIG_SND_ES968_MODULE 1 -#define CONFIG_SND_ES1688_MODULE 1 +#undef CONFIG_SND_DT019X +#undef CONFIG_SND_ES968 +#undef CONFIG_SND_ES1688 #define CONFIG_SND_ES18XX_MODULE 1 -#define CONFIG_SND_GUSCLASSIC_MODULE 1 -#define CONFIG_SND_GUSEXTREME_MODULE 1 -#define CONFIG_SND_GUSMAX_MODULE 1 -#define CONFIG_SND_INTERWAVE_MODULE 1 -#define CONFIG_SND_INTERWAVE_STB_MODULE 1 -#define CONFIG_SND_OPTI92X_AD1848_MODULE 1 -#define CONFIG_SND_OPTI92X_CS4231_MODULE 1 -#define CONFIG_SND_OPTI93X_MODULE 1 -#define CONFIG_SND_SB8_MODULE 1 +#undef CONFIG_SND_GUSCLASSIC +#undef CONFIG_SND_GUSEXTREME +#undef CONFIG_SND_GUSMAX +#undef CONFIG_SND_INTERWAVE +#undef CONFIG_SND_INTERWAVE_STB +#define CONFIG_SND_OPL3SA2_MODULE 1 +#undef CONFIG_SND_OPTI92X_AD1848 +#undef CONFIG_SND_OPTI92X_CS4231 +#undef CONFIG_SND_OPTI93X +#define CONFIG_SND_MIRO_MODULE 1 +#undef CONFIG_SND_SB8 #define CONFIG_SND_SB16_MODULE 1 #define CONFIG_SND_SBAWE_MODULE 1 -#define CONFIG_SND_SB16_CSP 1 +#undef CONFIG_SND_SB16_CSP +#undef CONFIG_SND_SGALAXY +#undef CONFIG_SND_SSCAPE #undef CONFIG_SND_WAVEFRONT -#define CONFIG_SND_ALS100_MODULE 1 -#define CONFIG_SND_AZT2320_MODULE 1 -#define CONFIG_SND_CMI8330_MODULE 1 -#define CONFIG_SND_DT019X_MODULE 1 -#define CONFIG_SND_OPL3SA2_MODULE 1 -#define CONFIG_SND_SGALAXY_MODULE 1 -#define CONFIG_SND_SSCAPE_MODULE 1 /* * PCI devices */ -#define CONFIG_SND_AC97_CODEC_MODULE 1 +#define CONFIG_SND_AD1889_MODULE 1 +#define CONFIG_SND_ALS300_MODULE 1 +#define CONFIG_SND_ALS4000_MODULE 1 #define CONFIG_SND_ALI5451_MODULE 1 #define CONFIG_SND_ATIIXP_MODULE 1 +#define CONFIG_SND_ATIIXP_MODEM_MODULE 1 #define CONFIG_SND_AU8810_MODULE 1 #define CONFIG_SND_AU8820_MODULE 1 #define CONFIG_SND_AU8830_MODULE 1 #define CONFIG_SND_AZT3328_MODULE 1 #define CONFIG_SND_BT87X_MODULE 1 +#undef CONFIG_SND_BT87X_OVERCLOCK +#define CONFIG_SND_CA0106_MODULE 1 +#define CONFIG_SND_CMIPCI_MODULE 1 +#define CONFIG_SND_CS4281_MODULE 1 #define CONFIG_SND_CS46XX_MODULE 1 #define CONFIG_SND_CS46XX_NEW_DSP 1 -#define CONFIG_SND_CS4281_MODULE 1 +#define CONFIG_SND_CS5535AUDIO_MODULE 1 #define CONFIG_SND_EMU10K1_MODULE 1 -#define CONFIG_SND_KORG1212_MODULE 1 -#define CONFIG_SND_MIXART_MODULE 1 -#define CONFIG_SND_NM256_MODULE 1 -#define CONFIG_SND_RME32_MODULE 1 -#define CONFIG_SND_RME96_MODULE 1 -#define CONFIG_SND_RME9652_MODULE 1 -#define CONFIG_SND_HDSP_MODULE 1 -#define CONFIG_SND_TRIDENT_MODULE 1 -#define CONFIG_SND_YMFPCI_MODULE 1 -#define CONFIG_SND_ALS4000_MODULE 1 -#define CONFIG_SND_CMIPCI_MODULE 1 +#define CONFIG_SND_EMU10K1X_MODULE 1 #define CONFIG_SND_ENS1370_MODULE 1 #define CONFIG_SND_ENS1371_MODULE 1 #define CONFIG_SND_ES1938_MODULE 1 #define CONFIG_SND_ES1968_MODULE 1 -#define CONFIG_SND_MAESTRO3_MODULE 1 #define CONFIG_SND_FM801_MODULE 1 +#define CONFIG_SND_FM801_TEA575X_BOOL 1 #define CONFIG_SND_FM801_TEA575X_MODULE 1 +#define CONFIG_SND_HDA_INTEL_MODULE 1 +#define CONFIG_SND_HDSP_MODULE 1 +#define CONFIG_SND_HDSPM_MODULE 1 #define CONFIG_SND_ICE1712_MODULE 1 #define CONFIG_SND_ICE1724_MODULE 1 #define CONFIG_SND_INTEL8X0_MODULE 1 #define CONFIG_SND_INTEL8X0M_MODULE 1 +#define CONFIG_SND_KORG1212_MODULE 1 +#define CONFIG_SND_MAESTRO3_MODULE 1 +#define CONFIG_SND_MIXART_MODULE 1 +#define CONFIG_SND_NM256_MODULE 1 +#define CONFIG_SND_PCXHR_MODULE 1 +#define CONFIG_SND_RIPTIDE_MODULE 1 +#define CONFIG_SND_RME32_MODULE 1 +#define CONFIG_SND_RME96_MODULE 1 +#define CONFIG_SND_RME9652_MODULE 1 #define CONFIG_SND_SONICVIBES_MODULE 1 +#define CONFIG_SND_TRIDENT_MODULE 1 #define CONFIG_SND_VIA82XX_MODULE 1 +#define CONFIG_SND_VIA82XX_MODEM_MODULE 1 #define CONFIG_SND_VX222_MODULE 1 +#define CONFIG_SND_YMFPCI_MODULE 1 /* - * ALSA USB devices + * USB devices */ #define CONFIG_SND_USB_AUDIO_MODULE 1 +#define CONFIG_SND_USB_USX2Y_MODULE 1 /* * PCMCIA devices */ #undef CONFIG_SND_VXPOCKET -#undef CONFIG_SND_VXP440 -#define CONFIG_SND_PDAUDIOCF_MODULE 1 +#undef CONFIG_SND_PDAUDIOCF /* * Open Sound System @@ -1906,6 +2623,9 @@ /* * USB support */ +#define CONFIG_USB_ARCH_HAS_HCD 1 +#define CONFIG_USB_ARCH_HAS_OHCI 1 +#define CONFIG_USB_ARCH_HAS_EHCI 1 #define CONFIG_USB 1 #undef CONFIG_USB_DEBUG @@ -1915,6 +2635,8 @@ #define CONFIG_USB_DEVICEFS 1 #undef CONFIG_USB_BANDWIDTH #undef CONFIG_USB_DYNAMIC_MINORS +#undef CONFIG_USB_SUSPEND +#undef CONFIG_USB_OTG /* * USB Host Controller Drivers @@ -1922,36 +2644,46 @@ #define CONFIG_USB_EHCI_HCD_MODULE 1 #define CONFIG_USB_EHCI_SPLIT_ISO 1 #define CONFIG_USB_EHCI_ROOT_HUB_TT 1 +#define CONFIG_USB_ISP116X_HCD_MODULE 1 #define CONFIG_USB_OHCI_HCD_MODULE 1 +#undef CONFIG_USB_OHCI_BIG_ENDIAN +#define CONFIG_USB_OHCI_LITTLE_ENDIAN 1 #define CONFIG_USB_UHCI_HCD_MODULE 1 +#define CONFIG_USB_SL811_HCD_MODULE 1 +#define CONFIG_USB_SL811_CS_MODULE 1 /* * USB Device Class drivers */ -#define CONFIG_USB_AUDIO_MODULE 1 +#define CONFIG_USB_ACM_MODULE 1 +#define CONFIG_USB_PRINTER_MODULE 1 /* - * USB Bluetooth TTY can only be used with disabled Bluetooth subsystem + * NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' + */ + +/* + * may also be needed; see USB_STORAGE Help for more information */ -#define CONFIG_USB_MIDI_MODULE 1 -#define CONFIG_USB_ACM_MODULE 1 -#define CONFIG_USB_PRINTER_MODULE 1 #define CONFIG_USB_STORAGE_MODULE 1 #undef CONFIG_USB_STORAGE_DEBUG #define CONFIG_USB_STORAGE_DATAFAB 1 #define CONFIG_USB_STORAGE_FREECOM 1 #define CONFIG_USB_STORAGE_ISD200 1 #define CONFIG_USB_STORAGE_DPCM 1 -#define CONFIG_USB_STORAGE_HP8200e 1 +#define CONFIG_USB_STORAGE_USBAT 1 #define CONFIG_USB_STORAGE_SDDR09 1 #define CONFIG_USB_STORAGE_SDDR55 1 #define CONFIG_USB_STORAGE_JUMPSHOT 1 +#define CONFIG_USB_STORAGE_ALAUDA 1 +#define CONFIG_USB_LIBUSUAL 1 /* - * USB Human Interface Devices (HID) + * USB Input Devices */ #define CONFIG_USB_HID 1 #define CONFIG_USB_HIDINPUT 1 +#undef CONFIG_USB_HIDINPUT_POWERBOOK #define CONFIG_HID_FF 1 #define CONFIG_HID_PID 1 #define CONFIG_LOGITECH_FF 1 @@ -1959,64 +2691,50 @@ #define CONFIG_USB_HIDDEV 1 #define CONFIG_USB_AIPTEK_MODULE 1 #define CONFIG_USB_WACOM_MODULE 1 +#define CONFIG_USB_ACECAD_MODULE 1 #define CONFIG_USB_KBTAB_MODULE 1 #define CONFIG_USB_POWERMATE_MODULE 1 -#define CONFIG_USB_MTOUCH_MODULE 1 -#define CONFIG_USB_EGALAX_MODULE 1 +#define CONFIG_USB_TOUCHSCREEN_MODULE 1 +#define CONFIG_USB_TOUCHSCREEN_EGALAX 1 +#define CONFIG_USB_TOUCHSCREEN_PANJIT 1 +#define CONFIG_USB_TOUCHSCREEN_3M 1 +#define CONFIG_USB_TOUCHSCREEN_ITM 1 +#undef CONFIG_USB_YEALINK #define CONFIG_USB_XPAD_MODULE 1 #define CONFIG_USB_ATI_REMOTE_MODULE 1 +#define CONFIG_USB_ATI_REMOTE2_MODULE 1 +#define CONFIG_USB_KEYSPAN_REMOTE_MODULE 1 +#define CONFIG_USB_APPLETOUCH_MODULE 1 /* * USB Imaging devices */ #define CONFIG_USB_MDC800_MODULE 1 #define CONFIG_USB_MICROTEK_MODULE 1 -#define CONFIG_USB_HPUSBSCSI_MODULE 1 - -/* - * USB Multimedia devices - */ -#define CONFIG_USB_DABUSB_MODULE 1 -#define CONFIG_USB_VICAM_MODULE 1 -#define CONFIG_USB_DSBR_MODULE 1 -#define CONFIG_USB_IBMCAM_MODULE 1 -#define CONFIG_USB_KONICAWC_MODULE 1 -#define CONFIG_USB_OV511_MODULE 1 -#define CONFIG_USB_SE401_MODULE 1 -#define CONFIG_USB_STV680_MODULE 1 -#define CONFIG_USB_W9968CF_MODULE 1 /* - * USB Network adaptors + * USB Network Adapters */ #define CONFIG_USB_CATC_MODULE 1 #define CONFIG_USB_KAWETH_MODULE 1 #define CONFIG_USB_PEGASUS_MODULE 1 #define CONFIG_USB_RTL8150_MODULE 1 #define CONFIG_USB_USBNET_MODULE 1 - -/* - * USB Host-to-Host Cables - */ +#define CONFIG_USB_NET_AX8817X_MODULE 1 +#define CONFIG_USB_NET_CDCETHER_MODULE 1 +#define CONFIG_USB_NET_GL620A_MODULE 1 +#define CONFIG_USB_NET_NET1080_MODULE 1 +#define CONFIG_USB_NET_PLUSB_MODULE 1 +#define CONFIG_USB_NET_RNDIS_HOST_MODULE 1 +#define CONFIG_USB_NET_CDC_SUBSET_MODULE 1 #define CONFIG_USB_ALI_M5632 1 #define CONFIG_USB_AN2720 1 #define CONFIG_USB_BELKIN 1 -#define CONFIG_USB_GENESYS 1 -#define CONFIG_USB_NET1080 1 -#define CONFIG_USB_PL2301 1 - -/* - * Intelligent USB Devices/Gadgets - */ #define CONFIG_USB_ARMLINUX 1 #define CONFIG_USB_EPSON2888 1 -#define CONFIG_USB_ZAURUS 1 -#define CONFIG_USB_CDCETHER 1 - -/* - * USB Network Adapters - */ -#define CONFIG_USB_AX8817X 1 +#define CONFIG_USB_NET_ZAURUS_MODULE 1 +#define CONFIG_USB_ZD1201_MODULE 1 +#define CONFIG_USB_MON 1 /* * USB port drivers @@ -2028,15 +2746,24 @@ */ #define CONFIG_USB_SERIAL_MODULE 1 #define CONFIG_USB_SERIAL_GENERIC 1 +#define CONFIG_USB_SERIAL_AIRPRIME_MODULE 1 +#define CONFIG_USB_SERIAL_ANYDATA_MODULE 1 +#define CONFIG_USB_SERIAL_ARK3116_MODULE 1 #define CONFIG_USB_SERIAL_BELKIN_MODULE 1 +#define CONFIG_USB_SERIAL_WHITEHEAT_MODULE 1 #define CONFIG_USB_SERIAL_DIGI_ACCELEPORT_MODULE 1 +#define CONFIG_USB_SERIAL_CP2101_MODULE 1 +#define CONFIG_USB_SERIAL_CYPRESS_M8_MODULE 1 #define CONFIG_USB_SERIAL_EMPEG_MODULE 1 #define CONFIG_USB_SERIAL_FTDI_SIO_MODULE 1 +#define CONFIG_USB_SERIAL_FUNSOFT_MODULE 1 #define CONFIG_USB_SERIAL_VISOR_MODULE 1 #define CONFIG_USB_SERIAL_IPAQ_MODULE 1 #define CONFIG_USB_SERIAL_IR_MODULE 1 #define CONFIG_USB_SERIAL_EDGEPORT_MODULE 1 #define CONFIG_USB_SERIAL_EDGEPORT_TI_MODULE 1 +#define CONFIG_USB_SERIAL_GARMIN_MODULE 1 +#define CONFIG_USB_SERIAL_IPW_MODULE 1 #define CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE 1 #define CONFIG_USB_SERIAL_KEYSPAN_MODULE 1 #define CONFIG_USB_SERIAL_KEYSPAN_MPR 1 @@ -2054,11 +2781,15 @@ #define CONFIG_USB_SERIAL_KLSI_MODULE 1 #define CONFIG_USB_SERIAL_KOBIL_SCT_MODULE 1 #define CONFIG_USB_SERIAL_MCT_U232_MODULE 1 +#define CONFIG_USB_SERIAL_NAVMAN_MODULE 1 #define CONFIG_USB_SERIAL_PL2303_MODULE 1 +#define CONFIG_USB_SERIAL_HP4X_MODULE 1 #define CONFIG_USB_SERIAL_SAFE_MODULE 1 #define CONFIG_USB_SERIAL_SAFE_PADDED 1 +#define CONFIG_USB_SERIAL_TI_MODULE 1 #define CONFIG_USB_SERIAL_CYBERJACK_MODULE 1 #define CONFIG_USB_SERIAL_XIRCOM_MODULE 1 +#define CONFIG_USB_SERIAL_OPTION_MODULE 1 #define CONFIG_USB_SERIAL_OMNINET_MODULE 1 #define CONFIG_USB_EZUSB 1 @@ -2066,22 +2797,111 @@ * USB Miscellaneous drivers */ #define CONFIG_USB_EMI62_MODULE 1 -#undef CONFIG_USB_EMI26 -#define CONFIG_USB_TIGL_MODULE 1 +#define CONFIG_USB_EMI26_MODULE 1 #define CONFIG_USB_AUERSWALD_MODULE 1 #define CONFIG_USB_RIO500_MODULE 1 #define CONFIG_USB_LEGOTOWER_MODULE 1 #define CONFIG_USB_LCD_MODULE 1 #define CONFIG_USB_LED_MODULE 1 #undef CONFIG_USB_CYTHERM +#define CONFIG_USB_PHIDGETKIT_MODULE 1 #define CONFIG_USB_PHIDGETSERVO_MODULE 1 +#define CONFIG_USB_IDMOUSE_MODULE 1 +#define CONFIG_USB_SISUSBVGA_MODULE 1 +#define CONFIG_USB_SISUSBVGA_CON 1 +#define CONFIG_USB_LD_MODULE 1 #define CONFIG_USB_TEST_MODULE 1 +/* + * USB DSL modem support + */ +#define CONFIG_USB_ATM_MODULE 1 +#define CONFIG_USB_SPEEDTOUCH_MODULE 1 +#define CONFIG_USB_CXACRU_MODULE 1 +#define CONFIG_USB_UEAGLEATM_MODULE 1 +#define CONFIG_USB_XUSBATM_MODULE 1 + /* * USB Gadget Support */ #undef CONFIG_USB_GADGET +/* + * MMC/SD Card support + */ +#define CONFIG_MMC_MODULE 1 +#undef CONFIG_MMC_DEBUG +#define CONFIG_MMC_BLOCK_MODULE 1 +#define CONFIG_MMC_SDHCI_MODULE 1 +#define CONFIG_MMC_WBSD_MODULE 1 + +/* + * LED devices + */ +#undef CONFIG_NEW_LEDS + +/* + * LED drivers + */ + +/* + * LED Triggers + */ + +/* + * InfiniBand support + */ +#define CONFIG_INFINIBAND_MODULE 1 +#define CONFIG_INFINIBAND_USER_MAD_MODULE 1 +#define CONFIG_INFINIBAND_USER_ACCESS_MODULE 1 +#define CONFIG_INFINIBAND_MTHCA_MODULE 1 +#define CONFIG_INFINIBAND_MTHCA_DEBUG 1 +#define CONFIG_INFINIBAND_IPOIB_MODULE 1 +#define CONFIG_INFINIBAND_IPOIB_DEBUG 1 +#define CONFIG_INFINIBAND_IPOIB_DEBUG_DATA 1 +#define CONFIG_INFINIBAND_SRP_MODULE 1 + +/* + * EDAC - error detection and reporting (RAS) (EXPERIMENTAL) + */ +#define CONFIG_EDAC 1 + +/* + * Reporting subsystems + */ +#undef CONFIG_EDAC_DEBUG +#define CONFIG_EDAC_MM_EDAC_MODULE 1 +#define CONFIG_EDAC_AMD76X_MODULE 1 +#define CONFIG_EDAC_E7XXX_MODULE 1 +#define CONFIG_EDAC_E752X_MODULE 1 +#define CONFIG_EDAC_I82875P_MODULE 1 +#define CONFIG_EDAC_I82860_MODULE 1 +#define CONFIG_EDAC_R82600_MODULE 1 +#define CONFIG_EDAC_POLL 1 + +/* + * Real Time Clock + */ +#define CONFIG_RTC_LIB_MODULE 1 +#define CONFIG_RTC_CLASS_MODULE 1 + +/* + * RTC interfaces + */ +#define CONFIG_RTC_INTF_SYSFS_MODULE 1 +#define CONFIG_RTC_INTF_PROC_MODULE 1 +#define CONFIG_RTC_INTF_DEV_MODULE 1 + +/* + * RTC drivers + */ +#define CONFIG_RTC_DRV_X1205_MODULE 1 +#define CONFIG_RTC_DRV_DS1672_MODULE 1 +#define CONFIG_RTC_DRV_PCF8563_MODULE 1 +#define CONFIG_RTC_DRV_RS5C372_MODULE 1 +#undef CONFIG_RTC_DRV_M48T86 +#undef CONFIG_RTC_DRV_TEST + /* * File systems */ @@ -2089,6 +2909,8 @@ #define CONFIG_EXT2_FS_XATTR 1 #define CONFIG_EXT2_FS_POSIX_ACL 1 #define CONFIG_EXT2_FS_SECURITY 1 +#define CONFIG_EXT2_FS_XIP 1 +#define CONFIG_FS_XIP 1 #define CONFIG_EXT3_FS_MODULE 1 #define CONFIG_EXT3_FS_XATTR 1 #define CONFIG_EXT3_FS_POSIX_ACL 1 @@ -2104,22 +2926,28 @@ #define CONFIG_REISERFS_FS_SECURITY 1 #define CONFIG_JFS_FS_MODULE 1 #define CONFIG_JFS_POSIX_ACL 1 +#define CONFIG_JFS_SECURITY 1 #undef CONFIG_JFS_DEBUG #undef CONFIG_JFS_STATISTICS #define CONFIG_FS_POSIX_ACL 1 #define CONFIG_XFS_FS_MODULE 1 -#undef CONFIG_XFS_RT +#define CONFIG_XFS_EXPORT 1 #define CONFIG_XFS_QUOTA 1 #define CONFIG_XFS_SECURITY 1 #define CONFIG_XFS_POSIX_ACL 1 +#undef CONFIG_XFS_RT +#define CONFIG_OCFS2_FS_MODULE 1 #define CONFIG_MINIX_FS_MODULE 1 #define CONFIG_ROMFS_FS_MODULE 1 +#define CONFIG_INOTIFY 1 #define CONFIG_QUOTA 1 #undef CONFIG_QFMT_V1 #define CONFIG_QFMT_V2 1 #define CONFIG_QUOTACTL 1 +#define CONFIG_DNOTIFY 1 #define CONFIG_AUTOFS_FS_MODULE 1 #define CONFIG_AUTOFS4_FS_MODULE 1 +#define CONFIG_FUSE_FS_MODULE 1 /* * CD-ROM/DVD Filesystems @@ -2129,6 +2957,7 @@ #define CONFIG_ZISOFS 1 #define CONFIG_ZISOFS_FS 1 #define CONFIG_UDF_FS_MODULE 1 +#define CONFIG_UDF_NLS 1 /* * DOS/FAT/NT Filesystems @@ -2136,6 +2965,8 @@ #define CONFIG_FAT_FS_MODULE 1 #define CONFIG_MSDOS_FS_MODULE 1 #define CONFIG_VFAT_FS_MODULE 1 +#define CONFIG_FAT_DEFAULT_CODEPAGE 437 +#define CONFIG_FAT_DEFAULT_IOCHARSET "ascii" #undef CONFIG_NTFS_FS /* @@ -2144,13 +2975,11 @@ #define CONFIG_PROC_FS 1 #define CONFIG_PROC_KCORE 1 #define CONFIG_SYSFS 1 -#undef CONFIG_DEVFS_FS -#define CONFIG_DEVPTS_FS_XATTR 1 -#define CONFIG_DEVPTS_FS_SECURITY 1 #define CONFIG_TMPFS 1 #define CONFIG_HUGETLBFS 1 #define CONFIG_HUGETLB_PAGE 1 #define CONFIG_RAMFS 1 +#define CONFIG_CONFIGFS_FS_MODULE 1 /* * Miscellaneous filesystems @@ -2166,37 +2995,52 @@ #undef CONFIG_JFFS_FS #define CONFIG_JFFS2_FS_MODULE 1 #define CONFIG_JFFS2_FS_DEBUG 0 -#define CONFIG_JFFS2_FS_NAND 1 +#define CONFIG_JFFS2_FS_WRITEBUFFER 1 +#define CONFIG_JFFS2_SUMMARY 1 +#undef CONFIG_JFFS2_COMPRESSION_OPTIONS +#define CONFIG_JFFS2_ZLIB 1 +#define CONFIG_JFFS2_RTIME 1 +#undef CONFIG_JFFS2_RUBIN #define CONFIG_CRAMFS_MODULE 1 +#define CONFIG_SQUASHFS_MODULE 1 +#undef CONFIG_SQUASHFS_EMBEDDED +#define CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE 3 +#undef CONFIG_SQUASHFS_VMALLOC #define CONFIG_VXFS_FS_MODULE 1 #undef CONFIG_HPFS_FS #define CONFIG_QNX4FS_FS_MODULE 1 -#undef CONFIG_QNX4FS_RW #define CONFIG_SYSV_FS_MODULE 1 #define CONFIG_UFS_FS_MODULE 1 -#undef CONFIG_UFS_FS_WRITE /* * Network File Systems */ #define CONFIG_NFS_FS_MODULE 1 #define CONFIG_NFS_V3 1 +#define CONFIG_NFS_V3_ACL 1 #define CONFIG_NFS_V4 1 #define CONFIG_NFS_DIRECTIO 1 #define CONFIG_NFSD_MODULE 1 +#define CONFIG_NFSD_V2_ACL 1 #define CONFIG_NFSD_V3 1 +#define CONFIG_NFSD_V3_ACL 1 #define CONFIG_NFSD_V4 1 #define CONFIG_NFSD_TCP 1 #define CONFIG_LOCKD_MODULE 1 #define CONFIG_LOCKD_V4 1 #define CONFIG_EXPORTFS_MODULE 1 +#define CONFIG_NFS_ACL_SUPPORT_MODULE 1 +#define CONFIG_NFS_COMMON 1 #define CONFIG_SUNRPC_MODULE 1 #define CONFIG_SUNRPC_GSS_MODULE 1 #define CONFIG_RPCSEC_GSS_KRB5_MODULE 1 -#define CONFIG_SMB_FS_MODULE 1 -#undef CONFIG_SMB_NLS_DEFAULT +#define CONFIG_RPCSEC_GSS_SPKM3_MODULE 1 +#undef CONFIG_SMB_FS #define CONFIG_CIFS_MODULE 1 #undef CONFIG_CIFS_STATS +#define CONFIG_CIFS_XATTR 1 +#define CONFIG_CIFS_POSIX 1 +#undef CONFIG_CIFS_EXPERIMENTAL #define CONFIG_NCP_FS_MODULE 1 #define CONFIG_NCPFS_PACKET_SIGNING 1 #define CONFIG_NCPFS_IOCTL_LOCKING 1 @@ -2206,8 +3050,10 @@ #define CONFIG_NCPFS_SMALLDOS 1 #define CONFIG_NCPFS_NLS 1 #define CONFIG_NCPFS_EXTRAS 1 -#undef CONFIG_CODA_FS +#define CONFIG_CODA_FS_MODULE 1 +#undef CONFIG_CODA_FS_OLD_API #undef CONFIG_AFS_FS +#define CONFIG_9P_FS_MODULE 1 /* * Partition Types @@ -2215,7 +3061,7 @@ #define CONFIG_PARTITION_ADVANCED 1 #undef CONFIG_ACORN_PARTITION #define CONFIG_OSF_PARTITION 1 -#undef CONFIG_AMIGA_PARTITION +#define CONFIG_AMIGA_PARTITION 1 #undef CONFIG_ATARI_PARTITION #define CONFIG_MAC_PARTITION 1 #define CONFIG_MSDOS_PARTITION 1 @@ -2224,10 +3070,10 @@ #define CONFIG_SOLARIS_X86_PARTITION 1 #define CONFIG_UNIXWARE_DISKLABEL 1 #undef CONFIG_LDM_PARTITION -#undef CONFIG_NEC98_PARTITION #define CONFIG_SGI_PARTITION 1 #undef CONFIG_ULTRIX_PARTITION #define CONFIG_SUN_PARTITION 1 +#define CONFIG_KARMA_PARTITION 1 #define CONFIG_EFI_PARTITION 1 /* @@ -2235,7 +3081,7 @@ */ #define CONFIG_NLS 1 #define CONFIG_NLS_DEFAULT "utf8" -#define CONFIG_NLS_CODEPAGE_437_MODULE 1 +#define CONFIG_NLS_CODEPAGE_437 1 #define CONFIG_NLS_CODEPAGE_737_MODULE 1 #define CONFIG_NLS_CODEPAGE_775_MODULE 1 #define CONFIG_NLS_CODEPAGE_850_MODULE 1 @@ -2258,6 +3104,7 @@ #define CONFIG_NLS_ISO8859_8_MODULE 1 #define CONFIG_NLS_CODEPAGE_1250_MODULE 1 #define CONFIG_NLS_CODEPAGE_1251_MODULE 1 +#define CONFIG_NLS_ASCII 1 #define CONFIG_NLS_ISO8859_1_MODULE 1 #define CONFIG_NLS_ISO8859_2_MODULE 1 #define CONFIG_NLS_ISO8859_3_MODULE 1 @@ -2274,41 +3121,68 @@ #define CONFIG_NLS_UTF8_MODULE 1 /* - * Profiling support + * Instrumentation Support */ #define CONFIG_PROFILING 1 #define CONFIG_OPROFILE_MODULE 1 +#define CONFIG_KPROBES 1 /* * Kernel hacking */ +#undef CONFIG_PRINTK_TIME +#define CONFIG_MAGIC_SYSRQ 1 #define CONFIG_DEBUG_KERNEL 1 -#define CONFIG_EARLY_PRINTK 1 -#define CONFIG_DEBUG_STACKOVERFLOW 1 -#undef CONFIG_DEBUG_STACK_USAGE +#define CONFIG_LOG_BUF_SHIFT 17 +#define CONFIG_DETECT_SOFTLOCKUP 1 +#define CONFIG_SCHEDSTATS 1 #undef CONFIG_DEBUG_SLAB -#define CONFIG_MAGIC_SYSRQ 1 -#undef CONFIG_DEBUG_SPINLOCK -#undef CONFIG_DEBUG_PAGEALLOC -#undef CONFIG_DEBUG_HIGHMEM -#define CONFIG_DEBUG_INFO 1 +#define CONFIG_DEBUG_MUTEXES 1 +#define CONFIG_DEBUG_SPINLOCK 1 #define CONFIG_DEBUG_SPINLOCK_SLEEP 1 +#undef CONFIG_DEBUG_KOBJECT +#define CONFIG_DEBUG_HIGHMEM 1 +#define CONFIG_DEBUG_BUGVERBOSE 1 +#define CONFIG_DEBUG_INFO 1 +#define CONFIG_DEBUG_FS 1 +#define CONFIG_DEBUG_VM 1 #undef CONFIG_FRAME_POINTER +#define CONFIG_UNWIND_INFO 1 +#undef CONFIG_FORCED_INLINING +#define CONFIG_BOOT_DELAY 1 +#undef CONFIG_RCU_TORTURE_TEST +#define CONFIG_EARLY_PRINTK 1 +#define CONFIG_DEBUG_STACKOVERFLOW 1 +#define CONFIG_DEBUG_STACK_USAGE 1 +#define CONFIG_STACK_BACKTRACE_COLS 2 + +/* + * Page alloc debug is incompatible with Software Suspend on i386 + */ +#define CONFIG_DEBUG_RODATA 1 +#define CONFIG_4KSTACKS 1 #define CONFIG_X86_FIND_SMP_CONFIG 1 #define CONFIG_X86_MPPARSE 1 +#define CONFIG_DOUBLEFAULT 1 /* * Security options */ +#define CONFIG_KEYS 1 +#define CONFIG_KEYS_DEBUG_PROC_KEYS 1 #define CONFIG_SECURITY 1 #define CONFIG_SECURITY_NETWORK 1 +#define CONFIG_SECURITY_NETWORK_XFRM 1 #define CONFIG_SECURITY_CAPABILITIES 1 #undef CONFIG_SECURITY_ROOTPLUG +#undef CONFIG_SECURITY_SECLVL #define CONFIG_SECURITY_SELINUX 1 #define CONFIG_SECURITY_SELINUX_BOOTPARAM 1 +#define CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE 1 #define CONFIG_SECURITY_SELINUX_DISABLE 1 #define CONFIG_SECURITY_SELINUX_DEVELOP 1 -#undef CONFIG_SECURITY_SELINUX_MLS +#define CONFIG_SECURITY_SELINUX_AVC_STATS 1 +#define CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE 1 /* * Cryptographic options @@ -2318,32 +3192,51 @@ #define CONFIG_CRYPTO_NULL_MODULE 1 #define CONFIG_CRYPTO_MD4_MODULE 1 #define CONFIG_CRYPTO_MD5 1 -#define CONFIG_CRYPTO_SHA1_MODULE 1 +#define CONFIG_CRYPTO_SHA1 1 #define CONFIG_CRYPTO_SHA256_MODULE 1 #define CONFIG_CRYPTO_SHA512_MODULE 1 +#define CONFIG_CRYPTO_WP512_MODULE 1 +#define CONFIG_CRYPTO_TGR192_MODULE 1 #define CONFIG_CRYPTO_DES_MODULE 1 #define CONFIG_CRYPTO_BLOWFISH_MODULE 1 #define CONFIG_CRYPTO_TWOFISH_MODULE 1 #define CONFIG_CRYPTO_SERPENT_MODULE 1 #define CONFIG_CRYPTO_AES_MODULE 1 +#define CONFIG_CRYPTO_AES_586_MODULE 1 #define CONFIG_CRYPTO_CAST5_MODULE 1 #define CONFIG_CRYPTO_CAST6_MODULE 1 +#define CONFIG_CRYPTO_TEA_MODULE 1 #define CONFIG_CRYPTO_ARC4_MODULE 1 +#define CONFIG_CRYPTO_KHAZAD_MODULE 1 +#define CONFIG_CRYPTO_ANUBIS_MODULE 1 #define CONFIG_CRYPTO_DEFLATE_MODULE 1 #define CONFIG_CRYPTO_MICHAEL_MIC_MODULE 1 #define CONFIG_CRYPTO_CRC32C_MODULE 1 #undef CONFIG_CRYPTO_TEST +#define CONFIG_CRYPTO_SIGNATURE 1 +#define CONFIG_CRYPTO_SIGNATURE_DSA 1 +#define CONFIG_CRYPTO_MPILIB 1 + +/* + * Hardware crypto devices + */ +#define CONFIG_CRYPTO_DEV_PADLOCK_MODULE 1 +#define CONFIG_CRYPTO_DEV_PADLOCK_AES 1 /* * Library routines */ +#define CONFIG_CRC_CCITT_MODULE 1 +#define CONFIG_CRC16_MODULE 1 #define CONFIG_CRC32 1 #define CONFIG_LIBCRC32C_MODULE 1 #define CONFIG_ZLIB_INFLATE 1 #define CONFIG_ZLIB_DEFLATE_MODULE 1 -#define CONFIG_X86_SMP 1 -#define CONFIG_X86_HT 1 +#define CONFIG_TEXTSEARCH 1 +#define CONFIG_TEXTSEARCH_KMP_MODULE 1 +#define CONFIG_TEXTSEARCH_BM_MODULE 1 +#define CONFIG_TEXTSEARCH_FSM_MODULE 1 +#define CONFIG_GENERIC_HARDIRQS 1 +#define CONFIG_GENERIC_IRQ_PROBE 1 #define CONFIG_X86_BIOS_REBOOT 1 -#define CONFIG_X86_TRAMPOLINE 1 -#define CONFIG_X86_STD_RESOURCES 1 -#define CONFIG_PC 1 +#define CONFIG_KTIME_SCALAR 1 diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 93535f093..9269df738 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -408,6 +408,8 @@ struct ethtool_ops { #define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ #define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ +#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ +#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 014999512..a4c919c22 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -507,6 +507,15 @@ static inline struct ext3_inode_info *EXT3_I(struct inode *inode) { return container_of(inode, struct ext3_inode_info, vfs_inode); } + +static inline int ext3_valid_inum(struct super_block *sb, unsigned long ino) +{ + return ino == EXT3_ROOT_INO || + ino == EXT3_JOURNAL_INO || + ino == EXT3_RESIZE_INO || + (ino >= EXT3_FIRST_INO(sb) && + ino <= le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)); +} #else /* Assume that user mode programs are passing in an ext3fs superblock, not * a kernel struct super_block. This will allow us to call the feature-test diff --git a/include/linux/gfp.h b/include/linux/gfp.h index a308228b7..83ece62bc 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -100,7 +100,11 @@ static inline int gfp_zone(gfp_t gfp) */ #ifndef HAVE_ARCH_FREE_PAGE -static inline void arch_free_page(struct page *page, int order) { } +/* + * If arch_free_page returns non-zero then the generic free_page code can + * immediately bail: the arch-specific function has done all the work. + */ +static inline int arch_free_page(struct page *page, int order) { return 0; } #endif extern struct page * diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 892c4ea1b..8f2bcfb85 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -25,10 +25,16 @@ static inline void flush_kernel_dcache_page(struct page *page) /* declarations for linux/mm/highmem.c */ unsigned int nr_free_highpages(void); +#ifdef CONFIG_XEN +void kmap_flush_unused(void); +#endif #else /* CONFIG_HIGHMEM */ static inline unsigned int nr_free_highpages(void) { return 0; } +#ifdef CONFIG_XEN +static inline void kmap_flush_unused(void) { } +#endif static inline void *kmap(struct page *page) { diff --git a/include/linux/idr.h b/include/linux/idr.h index d37c8d808..f559a719d 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -78,6 +78,7 @@ void *idr_find(struct idr *idp, int id); int idr_pre_get(struct idr *idp, gfp_t gfp_mask); int idr_get_new(struct idr *idp, void *ptr, int *id); int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id); +void *idr_replace(struct idr *idp, void *ptr, int id); void idr_remove(struct idr *idp, int id); void idr_destroy(struct idr *idp); void idr_init(struct idr *idp); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 2c08fdc2b..d55ff51ff 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -58,6 +58,12 @@ extern void disable_irq(unsigned int irq); extern void enable_irq(unsigned int irq); #endif +#ifdef CONFIG_HAVE_IRQ_IGNORE_UNHANDLED +int irq_ignore_unhandled(unsigned int irq); +#else +#define irq_ignore_unhandled(irq) 0 +#endif + #ifndef __ARCH_SET_SOFTIRQ_PENDING #define set_softirq_pending(x) (local_softirq_pending() = (x)) #define or_softirq_pending(x) (local_softirq_pending() |= (x)) diff --git a/include/linux/mm.h b/include/linux/mm.h index e4183fa67..51eea5b38 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -166,6 +166,9 @@ extern unsigned int kobjsize(const void *objp); #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ +#ifdef CONFIG_XEN +#define VM_FOREIGN 0x04000000 /* Has pages belonging to another VM */ +#endif #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS @@ -1026,6 +1029,13 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address, #define FOLL_GET 0x04 /* do get_page on page */ #define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */ +#ifdef CONFIG_XEN +typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr, + void *data); +extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, + unsigned long size, pte_fn_t fn, void *data); +#endif + #ifdef CONFIG_PROC_FS void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long); #else diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f4169bbb6..c5b97cf59 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -232,6 +232,7 @@ enum netdev_state_t __LINK_STATE_RX_SCHED, __LINK_STATE_LINKWATCH_PENDING, __LINK_STATE_DORMANT, + __LINK_STATE_QDISC_RUNNING, }; @@ -307,9 +308,17 @@ struct net_device #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ -#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */ +#define NETIF_F_GSO 2048 /* Enable software GSO. */ #define NETIF_F_LLTX 4096 /* LockLess TX */ -#define NETIF_F_UFO 8192 /* Can offload UDP Large Send*/ + + /* Segmentation offload features */ +#define NETIF_F_GSO_SHIFT 16 +#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) +#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT) +#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) + +#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) +#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) struct net_device *next_sched; @@ -398,6 +407,9 @@ struct net_device struct list_head qdisc_list; unsigned long tx_queue_len; /* Max frames per queue allowed */ + /* Partially transmitted GSO packet. */ + struct sk_buff *gso_skb; + /* ingress path synchronizer */ spinlock_t ingress_lock; struct Qdisc *qdisc_ingress; @@ -406,7 +418,7 @@ struct net_device * One part is mostly used on xmit path (device) */ /* hard_start_xmit synchronizer */ - spinlock_t xmit_lock ____cacheline_aligned_in_smp; + spinlock_t _xmit_lock ____cacheline_aligned_in_smp; /* cpu id of processor entered to hard_start_xmit or -1, if nobody entered there. */ @@ -532,6 +544,9 @@ struct packet_type { struct net_device *, struct packet_type *, struct net_device *); + struct sk_buff *(*gso_segment)(struct sk_buff *skb, + int features); + int (*gso_send_check)(struct sk_buff *skb); void *af_packet_priv; struct list_head list; }; @@ -679,7 +694,8 @@ extern int dev_change_name(struct net_device *, char *); extern int dev_set_mtu(struct net_device *, int); extern int dev_set_mac_address(struct net_device *, struct sockaddr *); -extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); +extern int dev_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev); extern void dev_init(void); @@ -889,11 +905,43 @@ static inline void __netif_rx_complete(struct net_device *dev) clear_bit(__LINK_STATE_RX_SCHED, &dev->state); } +static inline void netif_tx_lock(struct net_device *dev) +{ + spin_lock(&dev->_xmit_lock); + dev->xmit_lock_owner = smp_processor_id(); +} + +static inline void netif_tx_lock_bh(struct net_device *dev) +{ + spin_lock_bh(&dev->_xmit_lock); + dev->xmit_lock_owner = smp_processor_id(); +} + +static inline int netif_tx_trylock(struct net_device *dev) +{ + int ok = spin_trylock(&dev->_xmit_lock); + if (likely(ok)) + dev->xmit_lock_owner = smp_processor_id(); + return ok; +} + +static inline void netif_tx_unlock(struct net_device *dev) +{ + dev->xmit_lock_owner = -1; + spin_unlock(&dev->_xmit_lock); +} + +static inline void netif_tx_unlock_bh(struct net_device *dev) +{ + dev->xmit_lock_owner = -1; + spin_unlock_bh(&dev->_xmit_lock); +} + static inline void netif_tx_disable(struct net_device *dev) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); netif_stop_queue(dev); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } /* These functions live elsewhere (drivers/net/net_init.c, but related) */ @@ -921,6 +969,7 @@ extern int netdev_max_backlog; extern int weight_p; extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int skb_checksum_help(struct sk_buff *skb, int inward); +extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features); #ifdef CONFIG_BUG extern void netdev_rx_csum_fault(struct net_device *dev); #else @@ -940,6 +989,19 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); extern void linkwatch_run_queue(void); +static inline int skb_gso_ok(struct sk_buff *skb, int features) +{ + int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT; + return (features & feature) == feature; +} + +static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) +{ + return skb_is_gso(skb) && + (!skb_gso_ok(skb, dev->features) || + unlikely(skb->ip_summed != CHECKSUM_HW)); +} + #endif /* __KERNEL__ */ #endif /* _LINUX_DEV_H */ diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index a75b84bb9..178a97e1a 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -47,18 +47,26 @@ enum nf_br_hook_priorities { #define BRNF_BRIDGED 0x08 #define BRNF_NF_BRIDGE_PREROUTING 0x10 - /* Only used in br_forward.c */ -static inline -void nf_bridge_maybe_copy_header(struct sk_buff *skb) +static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) { + int err; + if (skb->nf_bridge) { if (skb->protocol == __constant_htons(ETH_P_8021Q)) { + err = skb_cow(skb, 18); + if (err) + return err; memcpy(skb->data - 18, skb->nf_bridge->data, 18); skb_push(skb, 4); - } else + } else { + err = skb_cow(skb, 16); + if (err) + return err; memcpy(skb->data - 16, skb->nf_bridge->data, 16); + } } + return 0; } /* This is called by the IP fragmenting code and it ensures there is diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 0d514b252..6c33ee68d 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -16,6 +16,10 @@ #include #include #include + +#ifdef CONFIG_XEN +#include +#endif struct super_block; struct dentry; @@ -27,6 +31,11 @@ struct oprofile_operations { /* create any necessary configuration files in the oprofile fs. * Optional. */ int (*create_files)(struct super_block * sb, struct dentry * root); + /* setup active domains with Xen */ + int (*set_active)(int *active_domains, unsigned int adomains); + /* setup passive domains with Xen */ + int (*set_passive)(int *passive_domains, unsigned int pdomains); + /* Do any necessary interrupt setup. Optional. */ int (*setup)(void); /* Do any necessary interrupt shutdown. Optional. */ @@ -78,6 +87,8 @@ void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event); /* add a backtrace entry, to be called from the ->backtrace callback */ void oprofile_add_trace(unsigned long eip); +/* add a domain switch entry */ +int oprofile_add_domain_switch(int32_t domain_id); /** * Create a file of the given name as a child of the given root, with diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 4550ab035..2bd4cbafc 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1242,6 +1242,7 @@ #define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 #define PCI_DEVICE_ID_VIA_3269_0 0x0269 #define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 +#define PCI_DEVICE_ID_VIA_3296_0 0x0296 #define PCI_DEVICE_ID_VIA_8363_0 0x0305 #define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 #define PCI_DEVICE_ID_VIA_8371_0 0x0391 @@ -1249,6 +1250,7 @@ #define PCI_DEVICE_ID_VIA_82C561 0x0561 #define PCI_DEVICE_ID_VIA_82C586_1 0x0571 #define PCI_DEVICE_ID_VIA_82C576 0x0576 +#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x0581 #define PCI_DEVICE_ID_VIA_82C586_0 0x0586 #define PCI_DEVICE_ID_VIA_82C596 0x0596 #define PCI_DEVICE_ID_VIA_82C597_0 0x0597 @@ -1289,10 +1291,11 @@ #define PCI_DEVICE_ID_VIA_8783_0 0x3208 #define PCI_DEVICE_ID_VIA_8237 0x3227 #define PCI_DEVICE_ID_VIA_8251 0x3287 -#define PCI_DEVICE_ID_VIA_3296_0 0x0296 +#define PCI_DEVICE_ID_VIA_8237A 0x3337 #define PCI_DEVICE_ID_VIA_8231 0x8231 #define PCI_DEVICE_ID_VIA_8231_4 0x8235 #define PCI_DEVICE_ID_VIA_8365_1 0x8305 +#define PCI_DEVICE_ID_VIA_CX700 0x8324 #define PCI_DEVICE_ID_VIA_8371_1 0x8391 #define PCI_DEVICE_ID_VIA_82C598_1 0x8598 #define PCI_DEVICE_ID_VIA_838X_1 0xB188 diff --git a/include/linux/pfn.h b/include/linux/pfn.h index bb01f8b92..ba2a86677 100644 --- a/include/linux/pfn.h +++ b/include/linux/pfn.h @@ -4,6 +4,6 @@ #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((x) << PAGE_SHIFT) +#define PFN_PHYS(x) ((unsigned long long)(x) << PAGE_SHIFT) #endif diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c219f2f5f..e5f6a6824 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -134,9 +134,10 @@ struct skb_frag_struct { struct skb_shared_info { atomic_t dataref; unsigned short nr_frags; - unsigned short tso_size; - unsigned short tso_segs; - unsigned short ufo_size; + unsigned short gso_size; + /* Warning: this field is not always filled in (UFO)! */ + unsigned short gso_segs; + unsigned short gso_type; unsigned int ip6_frag_id; struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; @@ -168,6 +169,14 @@ enum { SKB_FCLONE_CLONE, }; +enum { + SKB_GSO_TCPV4 = 1 << 0, + SKB_GSO_UDPV4 = 1 << 1, + + /* This indicates the skb is from an untrusted source. */ + SKB_GSO_DODGY = 1 << 2, +}; + /** * struct sk_buff - socket buffer * @next: Next buffer in list @@ -189,6 +198,8 @@ enum { * @local_df: allow local fragmentation * @cloned: Head may be cloned (check refcnt to be sure) * @nohdr: Payload reference only, must not modify header + * @proto_data_valid: Protocol data validated since arriving at localhost + * @proto_csum_blank: Protocol csum must be added before leaving localhost * @pkt_type: Packet class * @fclone: skbuff clone status * @ip_summed: Driver fed us an IP checksum @@ -265,7 +276,13 @@ struct sk_buff { nfctinfo:3; __u8 pkt_type:3, fclone:2, +#ifndef CONFIG_XEN ipvs_property:1; +#else + ipvs_property:1, + proto_data_valid:1, + proto_csum_blank:1; +#endif __be16 protocol; void (*destructor)(struct sk_buff *skb); @@ -322,7 +339,8 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, unsigned int size, - gfp_t priority); + gfp_t priority, + int fclone); extern void kfree_skbmem(struct sk_buff *skb); extern struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); @@ -967,15 +985,16 @@ static inline void skb_reserve(struct sk_buff *skb, int len) #define NET_SKB_PAD 16 #endif -extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc); +extern int ___pskb_trim(struct sk_buff *skb, unsigned int len); static inline void __skb_trim(struct sk_buff *skb, unsigned int len) { - if (!skb->data_len) { - skb->len = len; - skb->tail = skb->data + len; - } else - ___pskb_trim(skb, len, 0); + if (unlikely(skb->data_len)) { + WARN_ON(1); + return; + } + skb->len = len; + skb->tail = skb->data + len; } /** @@ -985,6 +1004,7 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len) * * Cut the length of a buffer down by removing data from the tail. If * the buffer is already under the length specified it is not modified. + * The skb must be linear. */ static inline void skb_trim(struct sk_buff *skb, unsigned int len) { @@ -995,12 +1015,10 @@ static inline void skb_trim(struct sk_buff *skb, unsigned int len) static inline int __pskb_trim(struct sk_buff *skb, unsigned int len) { - if (!skb->data_len) { - skb->len = len; - skb->tail = skb->data+len; - return 0; - } - return ___pskb_trim(skb, len, 1); + if (skb->data_len) + return ___pskb_trim(skb, len); + __skb_trim(skb, len); + return 0; } static inline int pskb_trim(struct sk_buff *skb, unsigned int len) @@ -1008,6 +1026,21 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len) return (len < skb->len) ? __pskb_trim(skb, len) : 0; } +/** + * pskb_trim_unique - remove end from a paged unique (not cloned) buffer + * @skb: buffer to alter + * @len: new length + * + * This is identical to pskb_trim except that the caller knows that + * the skb is not cloned so we should never get an error due to out- + * of-memory. + */ +static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len) +{ + int err = pskb_trim(skb, len); + BUG_ON(err); +} + /** * skb_orphan - orphan a buffer * @skb: buffer to orphan @@ -1062,7 +1095,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, return skb; } #else -extern struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask); +extern struct sk_buff *__dev_alloc_skb(unsigned int length, gfp_t gfp_mask); #endif /** @@ -1161,18 +1194,34 @@ static inline int skb_can_coalesce(struct sk_buff *skb, int i, return 0; } +static inline int __skb_linearize(struct sk_buff *skb) +{ + return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM; +} + /** * skb_linearize - convert paged skb to linear one * @skb: buffer to linarize - * @gfp: allocation mode * * If there is no free memory -ENOMEM is returned, otherwise zero * is returned and the old skb data released. */ -extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp); -static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) +static inline int skb_linearize(struct sk_buff *skb) +{ + return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0; +} + +/** + * skb_linearize_cow - make sure skb is linear and writable + * @skb: buffer to process + * + * If there is no free memory -ENOMEM is returned, otherwise zero + * is returned and the old skb data released. + */ +static inline int skb_linearize_cow(struct sk_buff *skb) { - return __skb_linearize(skb, gfp); + return skb_is_nonlinear(skb) || skb_cloned(skb) ? + __skb_linearize(skb) : 0; } /** @@ -1269,6 +1318,7 @@ extern void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); extern void skb_release_data(struct sk_buff *skb); +extern struct sk_buff *skb_segment(struct sk_buff *skb, int features); static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) @@ -1398,5 +1448,10 @@ static inline void nf_reset(struct sk_buff *skb) static inline void nf_reset(struct sk_buff *skb) {} #endif /* CONFIG_NETFILTER */ +static inline int skb_is_gso(const struct sk_buff *skb) +{ + return skb_shinfo(skb)->gso_size; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/include/linux/tty.h b/include/linux/tty.h index 87931555b..f13f49afe 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -297,8 +297,6 @@ extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); extern void tty_write_message(struct tty_struct *tty, char *msg); -extern void tty_get_termios(struct tty_driver *drv, int idx, struct termios *tio); - extern int is_orphaned_pgrp(int pgrp); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index b94d1ad92..75b5b9333 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -218,12 +218,13 @@ extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab); extern void qdisc_put_rtab(struct qdisc_rate_table *tab); -extern int qdisc_restart(struct net_device *dev); +extern void __qdisc_run(struct net_device *dev); static inline void qdisc_run(struct net_device *dev) { - while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0) - /* NOTHING */; + if (!netif_queue_stopped(dev) && + !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) + __qdisc_run(dev); } extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, diff --git a/include/net/protocol.h b/include/net/protocol.h index 6dc597061..d516c58ce 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -37,6 +37,9 @@ struct net_protocol { int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); + int (*gso_send_check)(struct sk_buff *skb); + struct sk_buff *(*gso_segment)(struct sk_buff *skb, + int features); int no_policy; }; diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index aa6033ca7..225dcea94 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -405,19 +405,6 @@ static inline int sctp_list_single_entry(struct list_head *head) return ((head->next != head) && (head->next == head->prev)); } -/* Calculate the size (in bytes) occupied by the data of an iovec. */ -static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) -{ - size_t retval = 0; - - for (; iovlen > 0; --iovlen) { - retval += iov->iov_len; - iov++; - } - - return retval; -} - /* Generate a random jitter in the range of -50% ~ +50% of input RTO. */ static inline __s32 sctp_jitter(__u32 rto) { diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 1eac3d0eb..de313de4f 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -221,8 +221,7 @@ struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *, const struct sctp_chunk *, __u32 tsn); struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *, - const struct sctp_chunk *, - const struct msghdr *); + const struct msghdr *, size_t msg_len); struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *, const struct sctp_chunk *, const __u8 *, diff --git a/include/net/sock.h b/include/net/sock.h index f6e3f99c0..924d3481b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1042,9 +1042,13 @@ static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) { __sk_dst_set(sk, dst); sk->sk_route_caps = dst->dev->features; + if (sk->sk_route_caps & NETIF_F_GSO) + sk->sk_route_caps |= NETIF_F_TSO; if (sk->sk_route_caps & NETIF_F_TSO) { if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len) sk->sk_route_caps &= ~NETIF_F_TSO; + else + sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; } } diff --git a/include/net/tcp.h b/include/net/tcp.h index c0f884027..8fa246247 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -568,13 +568,13 @@ struct tcp_skb_cb { */ static inline int tcp_skb_pcount(const struct sk_buff *skb) { - return skb_shinfo(skb)->tso_segs; + return skb_shinfo(skb)->gso_segs; } /* This is valid iff tcp_skb_pcount() > 1. */ static inline int tcp_skb_mss(const struct sk_buff *skb) { - return skb_shinfo(skb)->tso_size; + return skb_shinfo(skb)->gso_size; } static inline void tcp_dec_pcount_approx(__u32 *count, @@ -1079,6 +1079,9 @@ extern struct request_sock_ops tcp_request_sock_ops; extern int tcp_v4_destroy_sock(struct sock *sk); +extern int tcp_v4_gso_send_check(struct sk_buff *skb); +extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features); + #ifdef CONFIG_PROC_FS extern int tcp4_proc_init(void); extern void tcp4_proc_exit(void); diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 0196291f6..e5618b909 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -43,10 +43,6 @@ enum iscsi_uevent_e { ISCSI_UEVENT_GET_STATS = UEVENT_BASE + 10, ISCSI_UEVENT_GET_PARAM = UEVENT_BASE + 11, - ISCSI_UEVENT_TRANSPORT_EP_CONNECT = UEVENT_BASE + 12, - ISCSI_UEVENT_TRANSPORT_EP_POLL = UEVENT_BASE + 13, - ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT = UEVENT_BASE + 14, - /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, ISCSI_KEVENT_CONN_ERROR = KEVENT_BASE + 2, @@ -64,83 +60,61 @@ struct iscsi_uevent { uint32_t initial_cmdsn; } c_session; struct msg_destroy_session { + uint64_t session_handle; uint32_t sid; } d_session; struct msg_create_conn { - uint32_t sid; + uint64_t session_handle; uint32_t cid; + uint32_t sid; } c_conn; struct msg_bind_conn { - uint32_t sid; - uint32_t cid; - uint64_t transport_eph; + uint64_t session_handle; + uint64_t conn_handle; + uint32_t transport_fd; uint32_t is_leading; } b_conn; struct msg_destroy_conn { - uint32_t sid; + uint64_t conn_handle; uint32_t cid; } d_conn; struct msg_send_pdu { - uint32_t sid; - uint32_t cid; uint32_t hdr_size; uint32_t data_size; + uint64_t conn_handle; } send_pdu; struct msg_set_param { - uint32_t sid; - uint32_t cid; + uint64_t conn_handle; uint32_t param; /* enum iscsi_param */ - uint32_t len; + uint32_t value; } set_param; struct msg_start_conn { - uint32_t sid; - uint32_t cid; + uint64_t conn_handle; } start_conn; struct msg_stop_conn { - uint32_t sid; - uint32_t cid; uint64_t conn_handle; uint32_t flag; } stop_conn; struct msg_get_stats { - uint32_t sid; - uint32_t cid; + uint64_t conn_handle; } get_stats; - struct msg_transport_connect { - uint32_t non_blocking; - } ep_connect; - struct msg_transport_poll { - uint64_t ep_handle; - uint32_t timeout_ms; - } ep_poll; - struct msg_transport_disconnect { - uint64_t ep_handle; - } ep_disconnect; } u; union { /* messages k -> u */ + uint64_t handle; int retcode; struct msg_create_session_ret { + uint64_t session_handle; uint32_t sid; - uint32_t host_no; } c_session_ret; - struct msg_create_conn_ret { - uint32_t sid; - uint32_t cid; - } c_conn_ret; struct msg_recv_req { - uint32_t sid; - uint32_t cid; uint64_t recv_handle; + uint64_t conn_handle; } recv_req; struct msg_conn_error { - uint32_t sid; - uint32_t cid; + uint64_t conn_handle; uint32_t error; /* enum iscsi_err */ } connerror; - struct msg_transport_connect_ret { - uint64_t handle; - } ep_connect_ret; } r; } __attribute__ ((aligned (sizeof(uint64_t)))); @@ -165,66 +139,29 @@ enum iscsi_err { ISCSI_ERR_SESSION_FAILED = ISCSI_ERR_BASE + 13, ISCSI_ERR_HDR_DGST = ISCSI_ERR_BASE + 14, ISCSI_ERR_DATA_DGST = ISCSI_ERR_BASE + 15, - ISCSI_ERR_PARAM_NOT_FOUND = ISCSI_ERR_BASE + 16, - ISCSI_ERR_NO_SCSI_CMD = ISCSI_ERR_BASE + 17, + ISCSI_ERR_PARAM_NOT_FOUND = ISCSI_ERR_BASE + 16 }; /* * iSCSI Parameters (RFC3720) */ enum iscsi_param { - /* passed in using netlink set param */ - ISCSI_PARAM_MAX_RECV_DLENGTH, - ISCSI_PARAM_MAX_XMIT_DLENGTH, - ISCSI_PARAM_HDRDGST_EN, - ISCSI_PARAM_DATADGST_EN, - ISCSI_PARAM_INITIAL_R2T_EN, - ISCSI_PARAM_MAX_R2T, - ISCSI_PARAM_IMM_DATA_EN, - ISCSI_PARAM_FIRST_BURST, - ISCSI_PARAM_MAX_BURST, - ISCSI_PARAM_PDU_INORDER_EN, - ISCSI_PARAM_DATASEQ_INORDER_EN, - ISCSI_PARAM_ERL, - ISCSI_PARAM_IFMARKER_EN, - ISCSI_PARAM_OFMARKER_EN, - ISCSI_PARAM_EXP_STATSN, - ISCSI_PARAM_TARGET_NAME, - ISCSI_PARAM_TPGT, - ISCSI_PARAM_PERSISTENT_ADDRESS, - ISCSI_PARAM_PERSISTENT_PORT, - ISCSI_PARAM_SESS_RECOVERY_TMO, - - /* pased in through bind conn using transport_fd */ - ISCSI_PARAM_CONN_PORT, - ISCSI_PARAM_CONN_ADDRESS, - - /* must always be last */ - ISCSI_PARAM_MAX, + ISCSI_PARAM_MAX_RECV_DLENGTH = 0, + ISCSI_PARAM_MAX_XMIT_DLENGTH = 1, + ISCSI_PARAM_HDRDGST_EN = 2, + ISCSI_PARAM_DATADGST_EN = 3, + ISCSI_PARAM_INITIAL_R2T_EN = 4, + ISCSI_PARAM_MAX_R2T = 5, + ISCSI_PARAM_IMM_DATA_EN = 6, + ISCSI_PARAM_FIRST_BURST = 7, + ISCSI_PARAM_MAX_BURST = 8, + ISCSI_PARAM_PDU_INORDER_EN = 9, + ISCSI_PARAM_DATASEQ_INORDER_EN = 10, + ISCSI_PARAM_ERL = 11, + ISCSI_PARAM_IFMARKER_EN = 12, + ISCSI_PARAM_OFMARKER_EN = 13, }; - -#define ISCSI_MAX_RECV_DLENGTH (1 << ISCSI_PARAM_MAX_RECV_DLENGTH) -#define ISCSI_MAX_XMIT_DLENGTH (1 << ISCSI_PARAM_MAX_XMIT_DLENGTH) -#define ISCSI_HDRDGST_EN (1 << ISCSI_PARAM_HDRDGST_EN) -#define ISCSI_DATADGST_EN (1 << ISCSI_PARAM_DATADGST_EN) -#define ISCSI_INITIAL_R2T_EN (1 << ISCSI_PARAM_INITIAL_R2T_EN) -#define ISCSI_MAX_R2T (1 << ISCSI_PARAM_MAX_R2T) -#define ISCSI_IMM_DATA_EN (1 << ISCSI_PARAM_IMM_DATA_EN) -#define ISCSI_FIRST_BURST (1 << ISCSI_PARAM_FIRST_BURST) -#define ISCSI_MAX_BURST (1 << ISCSI_PARAM_MAX_BURST) -#define ISCSI_PDU_INORDER_EN (1 << ISCSI_PARAM_PDU_INORDER_EN) -#define ISCSI_DATASEQ_INORDER_EN (1 << ISCSI_PARAM_DATASEQ_INORDER_EN) -#define ISCSI_ERL (1 << ISCSI_PARAM_ERL) -#define ISCSI_IFMARKER_EN (1 << ISCSI_PARAM_IFMARKER_EN) -#define ISCSI_OFMARKER_EN (1 << ISCSI_PARAM_OFMARKER_EN) -#define ISCSI_EXP_STATSN (1 << ISCSI_PARAM_EXP_STATSN) -#define ISCSI_TARGET_NAME (1 << ISCSI_PARAM_TARGET_NAME) -#define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) -#define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) -#define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT) -#define ISCSI_SESS_RECOVERY_TMO (1 << ISCSI_PARAM_SESS_RECOVERY_TMO) -#define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) -#define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) +#define ISCSI_PARAM_MAX 14 #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) @@ -253,6 +190,7 @@ enum iscsi_param { * These flags describes reason of stop_conn() call */ #define STOP_CONN_TERM 0x1 +#define STOP_CONN_SUSPEND 0x2 #define STOP_CONN_RECOVER 0x3 #define ISCSI_STATS_CUSTOM_MAX 32 diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 02f6e4b9e..4feda05fd 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -21,6 +21,8 @@ #ifndef ISCSI_PROTO_H #define ISCSI_PROTO_H +#define ISCSI_VERSION_STR "0.3" +#define ISCSI_DATE_STR "22-Apr-2005" #define ISCSI_DRAFT20_VERSION 0x00 /* default iSCSI listen port for incoming connections */ diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index b684426a5..b41cf077e 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -2,7 +2,7 @@ * iSCSI transport class definitions * * Copyright (C) IBM Corporation, 2004 - * Copyright (C) Mike Christie, 2004 - 2006 + * Copyright (C) Mike Christie, 2004 - 2005 * Copyright (C) Dmitry Yusupov, 2004 - 2005 * Copyright (C) Alex Aizman, 2004 - 2005 * @@ -27,13 +27,9 @@ #include struct scsi_transport_template; -struct iscsi_transport; struct Scsi_Host; struct mempool_zone; struct iscsi_cls_conn; -struct iscsi_conn; -struct iscsi_cmd_task; -struct iscsi_mgmt_task; /** * struct iscsi_transport - iSCSI Transport template @@ -50,24 +46,6 @@ struct iscsi_mgmt_task; * @start_conn: set connection to be operational * @stop_conn: suspend/recover/terminate connection * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text. - * @session_recovery_timedout: notify LLD a block during recovery timed out - * @suspend_conn_recv: susepend the recv side of the connection - * @termincate_conn: destroy socket connection. Called with mutex lock. - * @init_cmd_task: Initialize a iscsi_cmd_task and any internal structs. - * Called from queuecommand with session lock held. - * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs. - * Called from iscsi_conn_send_generic with xmitmutex. - * @xmit_cmd_task: Requests LLD to transfer cmd task. Returns 0 or the - * the number of bytes transferred on success, and -Exyz - * value on error. - * @xmit_mgmt_task: Requests LLD to transfer mgmt task. Returns 0 or the - * the number of bytes transferred on success, and -Exyz - * value on error. - * @cleanup_cmd_task: requests LLD to fail cmd task. Called with xmitmutex - * and session->lock after the connection has been - * suspended and terminated during recovery. If called - * from abort task then connection is not suspended - * or terminated but sk_callback_lock is held * * Template API provided by iSCSI Transport */ @@ -75,58 +53,38 @@ struct iscsi_transport { struct module *owner; char *name; unsigned int caps; - /* LLD sets this to indicate what values it can export to sysfs */ - unsigned int param_mask; struct scsi_host_template *host_template; + /* LLD session/scsi_host data size */ + int hostdata_size; + /* LLD iscsi_host data size */ + int ihostdata_size; /* LLD connection data size */ int conndata_size; - /* LLD session data size */ - int sessiondata_size; int max_lun; unsigned int max_conn; unsigned int max_cmd_len; - struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it, - struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); + struct iscsi_cls_session *(*create_session) + (struct scsi_transport_template *t, uint32_t sn, uint32_t *sid); void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); int (*bind_conn) (struct iscsi_cls_session *session, struct iscsi_cls_conn *cls_conn, - uint64_t transport_eph, int is_leading); + uint32_t transport_fd, int is_leading); int (*start_conn) (struct iscsi_cls_conn *conn); void (*stop_conn) (struct iscsi_cls_conn *conn, int flag); void (*destroy_conn) (struct iscsi_cls_conn *conn); int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param, uint32_t value); int (*get_conn_param) (struct iscsi_cls_conn *conn, - enum iscsi_param param, uint32_t *value); + enum iscsi_param param, + uint32_t *value); int (*get_session_param) (struct iscsi_cls_session *session, enum iscsi_param param, uint32_t *value); - int (*get_conn_str_param) (struct iscsi_cls_conn *conn, - enum iscsi_param param, char *buf); - int (*get_session_str_param) (struct iscsi_cls_session *session, - enum iscsi_param param, char *buf); int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); - void (*suspend_conn_recv) (struct iscsi_conn *conn); - void (*terminate_conn) (struct iscsi_conn *conn); - void (*init_cmd_task) (struct iscsi_cmd_task *ctask); - void (*init_mgmt_task) (struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask, - char *data, uint32_t data_size); - int (*xmit_cmd_task) (struct iscsi_conn *conn, - struct iscsi_cmd_task *ctask); - void (*cleanup_cmd_task) (struct iscsi_conn *conn, - struct iscsi_cmd_task *ctask); - int (*xmit_mgmt_task) (struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask); - void (*session_recovery_timedout) (struct iscsi_cls_session *session); - int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking, - uint64_t *ep_handle); - int (*ep_poll) (uint64_t ep_handle, int timeout_ms); - void (*ep_disconnect) (uint64_t ep_handle); }; /* @@ -142,26 +100,10 @@ extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error); extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); - -/* Connection's states */ -#define ISCSI_CONN_INITIAL_STAGE 0 -#define ISCSI_CONN_STARTED 1 -#define ISCSI_CONN_STOPPED 2 -#define ISCSI_CONN_CLEANUP_WAIT 3 - struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ void *dd_data; /* LLD private data */ struct iscsi_transport *transport; - uint32_t cid; /* connection id */ - - /* portal/group values we got during discovery */ - char *persistent_address; - int persistent_port; - /* portal/group values we are currently using */ - char *address; - int port; - int active; /* must be accessed with the connlock */ struct device dev; /* sysfs transport/container device */ struct mempool_zone *z_error; @@ -172,32 +114,9 @@ struct iscsi_cls_conn { #define iscsi_dev_to_conn(_dev) \ container_of(_dev, struct iscsi_cls_conn, dev) -/* Session's states */ -#define ISCSI_STATE_FREE 1 -#define ISCSI_STATE_LOGGED_IN 2 -#define ISCSI_STATE_FAILED 3 -#define ISCSI_STATE_TERMINATE 4 -#define ISCSI_STATE_IN_RECOVERY 5 -#define ISCSI_STATE_RECOVERY_FAILED 6 - struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ - struct list_head host_list; struct iscsi_transport *transport; - - /* iSCSI values used as unique id by userspace. */ - char *targetname; - int tpgt; - - /* recovery fields */ - int recovery_tmo; - struct work_struct recovery_work; - - int target_id; - int channel; - - int sid; /* session id */ - void *dd_data; /* LLD private data */ struct device dev; /* sysfs transport/container device */ }; @@ -207,22 +126,22 @@ struct iscsi_cls_session { #define iscsi_session_to_shost(_session) \ dev_to_shost(_session->dev.parent) -struct iscsi_host { - int next_target_id; - struct list_head sessions; - struct mutex mutex; -}; - /* * session and connection functions that can be used by HW iSCSI LLDs */ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, - struct iscsi_transport *t, int channel); + struct iscsi_transport *t); extern int iscsi_destroy_session(struct iscsi_cls_session *session); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, uint32_t cid); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); -extern void iscsi_unblock_session(struct iscsi_cls_session *session); -extern void iscsi_block_session(struct iscsi_cls_session *session); + +/* + * session functions used by software iscsi + */ +extern struct Scsi_Host * +iscsi_transport_create_session(struct scsi_transport_template *scsit, + struct iscsi_transport *transport); +extern int iscsi_transport_destroy_session(struct Scsi_Host *shost); #endif diff --git a/include/sound/initval.h b/include/sound/initval.h index d29e3d31d..d45170b9e 100644 --- a/include/sound/initval.h +++ b/include/sound/initval.h @@ -62,7 +62,8 @@ static int snd_legacy_find_free_irq(int *irq_table) { while (*irq_table != -1) { if (!request_irq(*irq_table, snd_legacy_empty_irq_handler, - SA_INTERRUPT, "ALSA Test IRQ", (void *) irq_table)) { + SA_INTERRUPT | SA_PROBEIRQ, "ALSA Test IRQ", + (void *) irq_table)) { free_irq(*irq_table, (void *) irq_table); return *irq_table; } diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt index 0b46a5dff..17ab32232 100644 --- a/kernel/Kconfig.preempt +++ b/kernel/Kconfig.preempt @@ -35,6 +35,7 @@ config PREEMPT_VOLUNTARY config PREEMPT bool "Preemptible Kernel (Low-Latency Desktop)" + depends on !XEN help This option reduces the latency of the kernel by making all kernel code (that is not executing in a critical section) diff --git a/kernel/fork.c b/kernel/fork.c index fcaaa9978..471d19f71 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -280,6 +280,9 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (retval) goto out; } +#ifdef arch_dup_mmap + arch_dup_mmap(mm, oldmm); +#endif retval = 0; out: up_write(&mm->mmap_sem); diff --git a/kernel/futex.c b/kernel/futex.c index 9ddf5010a..c27bb560b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -594,6 +594,7 @@ static int unqueue_me(struct futex_q *q) /* In the common case we don't take the spinlock, which is nice. */ retry: lock_ptr = q->lock_ptr; + barrier(); if (lock_ptr != 0) { spin_lock(lock_ptr); /* diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 1279e3499..97d555999 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -204,14 +204,10 @@ int setup_irq(unsigned int irq, struct irqaction * new) p = &desc->action; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - goto mismatch; - -#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) - /* All handlers must agree on per-cpuness */ - if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU)) - goto mismatch; -#endif + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } /* add new interrupt at end of irq queue */ do { @@ -222,10 +218,7 @@ int setup_irq(unsigned int irq, struct irqaction * new) } *p = new; -#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) - if (new->flags & SA_PERCPU_IRQ) - desc->status |= IRQ_PER_CPU; -#endif + if (!shared) { desc->depth = 0; desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | @@ -243,14 +236,6 @@ int setup_irq(unsigned int irq, struct irqaction * new) register_handler_proc(irq, new); return 0; - -mismatch: - spin_unlock_irqrestore(&desc->lock, flags); - if (!(new->flags & SA_PROBEIRQ)) { - printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__); - dump_stack(); - } - return -EBUSY; } /** @@ -273,7 +258,6 @@ void free_irq(unsigned int irq, void *dev_id) struct irqaction **p; unsigned long flags; - WARN_ON(in_interrupt()); if (irq >= NR_IRQS) return; diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 7df9abd5e..f9353e960 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -137,7 +137,8 @@ void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, struct pt_regs *regs) { if (action_ret != IRQ_HANDLED) { - desc->irqs_unhandled++; + if (!irq_ignore_unhandled(irq)) + desc->irqs_unhandled++; if (action_ret != IRQ_NONE) report_bad_irq(irq, desc, action_ret); } diff --git a/kernel/sched.c b/kernel/sched.c index 60bff8bec..026ba1f6c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4189,17 +4189,22 @@ asmlinkage long sys_sched_yield(void) return 0; } -static inline void __cond_resched(void) +static inline int __resched_legal(int expected_preempt_count) +{ + if (unlikely(preempt_count() != expected_preempt_count)) + return 0; + if (unlikely(system_state != SYSTEM_RUNNING)) + return 0; + return 1; +} + +static void __cond_resched(void) { /* * The BKS might be reacquired before we have dropped * PREEMPT_ACTIVE, which could trigger a second * cond_resched() call. */ - if (unlikely(preempt_count())) - return; - if (unlikely(system_state != SYSTEM_RUNNING)) - return; do { add_preempt_count(PREEMPT_ACTIVE); schedule(); @@ -4209,13 +4214,12 @@ static inline void __cond_resched(void) int __sched cond_resched(void) { - if (need_resched()) { + if (need_resched() && __resched_legal(0)) { __cond_resched(); return 1; } return 0; } - EXPORT_SYMBOL(cond_resched); /* @@ -4236,7 +4240,7 @@ int cond_resched_lock(spinlock_t *lock) ret = 1; spin_lock(lock); } - if (need_resched()) { + if (need_resched() && __resched_legal(1)) { _raw_spin_unlock(lock); preempt_enable_no_resched(); __cond_resched(); @@ -4245,14 +4249,13 @@ int cond_resched_lock(spinlock_t *lock) } return ret; } - EXPORT_SYMBOL(cond_resched_lock); int __sched cond_resched_softirq(void) { BUG_ON(!in_softirq()); - if (need_resched()) { + if (need_resched() && __resched_legal(0)) { __local_bh_enable(); __cond_resched(); local_bh_disable(); @@ -4260,10 +4263,8 @@ int __sched cond_resched_softirq(void) } return 0; } - EXPORT_SYMBOL(cond_resched_softirq); - /** * yield - yield the current processor to other threads. * diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index dcfb5d731..51cacd111 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -111,7 +111,6 @@ static int stop_machine(void) /* If some failed, kill them all. */ if (ret < 0) { stopmachine_set_state(STOPMACHINE_EXIT); - up(&stopmachine_mutex); return ret; } diff --git a/kernel/timer.c b/kernel/timer.c index 2f8cdbe00..20a4bca5e 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -543,6 +543,22 @@ found: } spin_unlock(&base->lock); + /* + * It can happen that other CPUs service timer IRQs and increment + * jiffies, but we have not yet got a local timer tick to process + * the timer wheels. In that case, the expiry time can be before + * jiffies, but since the high-resolution timer here is relative to + * jiffies, the default expression when high-resolution timers are + * not active, + * + * time_before(MAX_JIFFY_OFFSET + jiffies, expires) + * + * would falsely evaluate to true. If that is the case, just + * return jiffies so that we can immediately fire the local timer + */ + if (time_before(expires, jiffies)) + return jiffies; + /* * It can happen that other CPUs service timer IRQs and increment * jiffies, but we have not yet got a local timer tick to process @@ -971,46 +987,18 @@ asmlinkage long sys_getpid(void) } /* - * Accessing ->group_leader->real_parent is not SMP-safe, it could - * change from under us. However, rather than getting any lock - * we can use an optimistic algorithm: get the parent - * pid, and go back and check that the parent is still - * the same. If it has changed (which is extremely unlikely - * indeed), we just try again.. - * - * NOTE! This depends on the fact that even if we _do_ - * get an old value of "parent", we can happily dereference - * the pointer (it was and remains a dereferencable kernel pointer - * no matter what): we just can't necessarily trust the result - * until we know that the parent pointer is valid. - * - * NOTE2: ->group_leader never changes from under us. + * Accessing ->real_parent is not SMP-safe, it could + * change from under us. However, we can use a stale + * value of ->real_parent under rcu_read_lock(), see + * release_task()->call_rcu(delayed_put_task_struct). */ asmlinkage long sys_getppid(void) { int pid; - struct task_struct *me = current; - struct task_struct *parent; - parent = me->group_leader->real_parent; - for (;;) { - pid = parent->tgid; -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) -{ - struct task_struct *old = parent; - - /* - * Make sure we read the pid before re-reading the - * parent pointer: - */ - smp_rmb(); - parent = me->group_leader->real_parent; - if (old != parent) - continue; -} -#endif - break; - } + rcu_read_lock(); + pid = rcu_dereference(current->real_parent)->tgid; + rcu_read_unlock(); return vx_map_pid(pid); } @@ -1025,7 +1013,7 @@ asmlinkage long do_getxpid(long *ppid) *ppid = sys_getppid(); return sys_getpid(); } - + #else /* _alpha_ */ asmlinkage long sys_getuid(void) diff --git a/lib/Makefile b/lib/Makefile index b830c9a15..033ff7c67 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -48,6 +48,9 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o obj-$(CONFIG_SWIOTLB) += swiotlb.o +ifneq ($(CONFIG_XEN_IA64_DOM0_NON_VP),y) +swiotlb-$(CONFIG_XEN) := ../arch/i386/kernel/swiotlb.o +endif hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/idr.c b/lib/idr.c index de19030a9..4d0968195 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -29,6 +29,7 @@ #include #include #endif +#include #include #include @@ -398,6 +399,48 @@ void *idr_find(struct idr *idp, int id) } EXPORT_SYMBOL(idr_find); +/** + * idr_replace - replace pointer for given id + * @idp: idr handle + * @ptr: pointer you want associated with the id + * @id: lookup key + * + * Replace the pointer registered with an id and return the old value. + * A -ENOENT return indicates that @id was not found. + * A -EINVAL return indicates that @id was not within valid constraints. + * + * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove(). + */ +void *idr_replace(struct idr *idp, void *ptr, int id) +{ + int n; + struct idr_layer *p, *old_p; + + n = idp->layers * IDR_BITS; + p = idp->top; + + id &= MAX_ID_MASK; + + if (id >= (1 << n)) + return ERR_PTR(-EINVAL); + + n -= IDR_BITS; + while ((n > 0) && p) { + p = p->ary[(id >> n) & IDR_MASK]; + n -= IDR_BITS; + } + + n = id & IDR_MASK; + if (unlikely(p == NULL || !test_bit(n, &p->bitmap))) + return ERR_PTR(-ENOENT); + + old_p = p->ary[n]; + p->ary[n] = ptr; + + return old_p; +} +EXPORT_SYMBOL(idr_replace); + static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache, unsigned long flags) { diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index 34022dd9a..8ebd8ea08 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -150,6 +150,7 @@ static void rwlock_bug(rwlock_t *lock, const char *msg) #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) +#if 0 /* __write_lock_debug() can lock up - maybe this can too? */ static void __read_lock_debug(rwlock_t *lock) { int print_once = 1; @@ -171,12 +172,12 @@ static void __read_lock_debug(rwlock_t *lock) } } } +#endif void _raw_read_lock(rwlock_t *lock) { RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); - if (unlikely(!__raw_read_trylock(&lock->raw_lock))) - __read_lock_debug(lock); + __raw_read_lock(&lock->raw_lock); } int _raw_read_trylock(rwlock_t *lock) @@ -222,6 +223,7 @@ static inline void debug_write_unlock(rwlock_t *lock) lock->owner_cpu = -1; } +#if 0 /* This can cause lockups */ static void __write_lock_debug(rwlock_t *lock) { int print_once = 1; @@ -243,12 +245,12 @@ static void __write_lock_debug(rwlock_t *lock) } } } +#endif void _raw_write_lock(rwlock_t *lock) { debug_write_lock_before(lock); - if (unlikely(!__raw_write_trylock(&lock->raw_lock))) - __write_lock_debug(lock); + __raw_write_lock(&lock->raw_lock); debug_write_lock_after(lock); } diff --git a/lib/ts_bm.c b/lib/ts_bm.c index c4c1ac5fb..791726579 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c @@ -112,15 +112,14 @@ static int subpattern(u8 *pattern, int i, int j, int g) return ret; } -static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, - unsigned int len) +static void compute_prefix_tbl(struct ts_bm *bm) { int i, j, g; for (i = 0; i < ASIZE; i++) - bm->bad_shift[i] = len; - for (i = 0; i < len - 1; i++) - bm->bad_shift[pattern[i]] = len - 1 - i; + bm->bad_shift[i] = bm->patlen; + for (i = 0; i < bm->patlen - 1; i++) + bm->bad_shift[bm->pattern[i]] = bm->patlen - 1 - i; /* Compute the good shift array, used to match reocurrences * of a subpattern */ @@ -151,8 +150,8 @@ static struct ts_config *bm_init(const void *pattern, unsigned int len, bm = ts_config_priv(conf); bm->patlen = len; bm->pattern = (u8 *) bm->good_shift + prefix_tbl_len; - compute_prefix_tbl(bm, pattern, len); memcpy(bm->pattern, pattern, len); + compute_prefix_tbl(bm); return conf; } diff --git a/mm/Kconfig b/mm/Kconfig index 67b3f74ca..ab1007556 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -115,7 +115,7 @@ config SPARSEMEM_EXTREME # eventually, we can have this option just 'select SPARSEMEM' config MEMORY_HOTPLUG bool "Allow for memory hot-add" - depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND + depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG comment "Memory hotplug is currently incompatible with Software Suspend" depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND @@ -126,12 +126,16 @@ comment "Memory hotplug is currently incompatible with Software Suspend" # Default to 4 for wider testing, though 8 might be more appropriate. # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. # PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. +# XEN on x86 architecture uses the mapping field on pagetable pages to store a +# pointer to the destructor. This conflicts with pte_lock_deinit(). # config SPLIT_PTLOCK_CPUS int default "4096" if ARM && !CPU_CACHE_VIPT default "4096" if PARISC && !PA20 - default "4096" + default "4096" if X86_XEN || X86_64_XEN + default "4096" if !64BIT + default "4" # # support for page migration diff --git a/mm/filemap.c b/mm/filemap.c index 4b0449581..96f354e18 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -518,18 +518,11 @@ EXPORT_SYMBOL(unlock_page); */ void end_page_writeback(struct page *page) { - struct zone *zone = page_zone(page); if (!TestClearPageReclaim(page) || rotate_reclaimable_page(page)) { if (!test_clear_page_writeback(page)) BUG(); } smp_mb__after_clear_bit(); - if (zone->all_unreclaimable) { - spin_lock(&zone->lock); - zone->all_unreclaimable = 0; - zone->pages_scanned = 0; - spin_unlock(&zone->lock); - } wake_up_page(page, PG_writeback); } EXPORT_SYMBOL(end_page_writeback); @@ -2022,14 +2015,21 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, do { unsigned long index; unsigned long offset; - unsigned long maxlen; size_t copied; offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */ index = pos >> PAGE_CACHE_SHIFT; bytes = PAGE_CACHE_SIZE - offset; - if (bytes > count) - bytes = count; + + /* Limit the size of the copy to the caller's write size */ + bytes = min(bytes, count); + + /* + * Limit the size of the copy to that of the current segment, + * because fault_in_pages_readable() doesn't know how to walk + * segments. + */ + bytes = min(bytes, cur_iov->iov_len - iov_base); /* * Bring in the user page that we will copy from _first_. @@ -2037,10 +2037,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, * same page as we're writing to, without it being marked * up-to-date. */ - maxlen = cur_iov->iov_len - iov_base; - if (maxlen > bytes) - maxlen = bytes; - fault_in_pages_readable(buf, maxlen); + fault_in_pages_readable(buf, bytes); page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec); if (!page) { @@ -2048,6 +2045,12 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, break; } + if (unlikely(bytes == 0)) { + status = 0; + copied = 0; + goto zero_length_segment; + } + status = a_ops->prepare_write(file, page, offset, offset+bytes); if (unlikely(status)) { loff_t isize = i_size_read(inode); @@ -2077,7 +2080,8 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, page_cache_release(page); continue; } - if (likely(copied > 0)) { +zero_length_segment: + if (likely(copied >= 0)) { if (!status) status = copied; diff --git a/mm/filemap.h b/mm/filemap.h index 13793ba0c..efd01426b 100644 --- a/mm/filemap.h +++ b/mm/filemap.h @@ -78,7 +78,7 @@ filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) const struct iovec *iov = *iovp; size_t base = *basep; - while (bytes) { + do { int copy = min(bytes, iov->iov_len - base); bytes -= copy; @@ -87,7 +87,7 @@ filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) iov++; base = 0; } - } + } while (bytes); *iovp = iov; *basep = base; } diff --git a/mm/highmem.c b/mm/highmem.c index 9b274fdf9..a02c6dec9 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -142,6 +142,17 @@ start: return vaddr; } +#ifdef CONFIG_XEN +void kmap_flush_unused(void) +{ + spin_lock(&kmap_lock); + flush_all_zero_pkmaps(); + spin_unlock(&kmap_lock); +} + +EXPORT_SYMBOL(kmap_flush_unused); +#endif + void fastcall *kmap_high(struct page *page) { unsigned long vaddr; diff --git a/mm/memory.c b/mm/memory.c index 1bd040470..9f75bb2ca 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -402,7 +402,8 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_ * and that the resulting page looks ok. */ if (unlikely(!pfn_valid(pfn))) { - print_bad_pte(vma, pte, addr); + if (!(vma->vm_flags & VM_RESERVED)) + print_bad_pte(vma, pte, addr); return NULL; } @@ -1017,6 +1018,26 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, continue; } +#ifdef CONFIG_XEN + if (vma && (vma->vm_flags & VM_FOREIGN)) { + struct page **map = vma->vm_private_data; + int offset = (start - vma->vm_start) >> PAGE_SHIFT; + if (map[offset] != NULL) { + if (pages) { + struct page *page = map[offset]; + + pages[i] = page; + get_page(page); + } + if (vmas) + vmas[i] = vma; + i++; + start += PAGE_SIZE; + len--; + continue; + } + } +#endif if (!vma || (vma->vm_flags & (VM_IO | VM_PFNMAP)) || !(vm_flags & vma->vm_flags)) return i ? : -EFAULT; @@ -1356,6 +1377,102 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, } EXPORT_SYMBOL(remap_pfn_range); +#ifdef CONFIG_XEN +static inline int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, + unsigned long addr, unsigned long end, + pte_fn_t fn, void *data) +{ + pte_t *pte; + int err; + struct page *pmd_page; + spinlock_t *ptl; + + pte = (mm == &init_mm) ? + pte_alloc_kernel(pmd, addr) : + pte_alloc_map_lock(mm, pmd, addr, &ptl); + if (!pte) + return -ENOMEM; + + BUG_ON(pmd_huge(*pmd)); + + pmd_page = pmd_page(*pmd); + + do { + err = fn(pte, pmd_page, addr, data); + if (err) + break; + } while (pte++, addr += PAGE_SIZE, addr != end); + + if (mm != &init_mm) + pte_unmap_unlock(pte-1, ptl); + return err; +} + +static inline int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud, + unsigned long addr, unsigned long end, + pte_fn_t fn, void *data) +{ + pmd_t *pmd; + unsigned long next; + int err; + + pmd = pmd_alloc(mm, pud, addr); + if (!pmd) + return -ENOMEM; + do { + next = pmd_addr_end(addr, end); + err = apply_to_pte_range(mm, pmd, addr, next, fn, data); + if (err) + break; + } while (pmd++, addr = next, addr != end); + return err; +} + +static inline int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd, + unsigned long addr, unsigned long end, + pte_fn_t fn, void *data) +{ + pud_t *pud; + unsigned long next; + int err; + + pud = pud_alloc(mm, pgd, addr); + if (!pud) + return -ENOMEM; + do { + next = pud_addr_end(addr, end); + err = apply_to_pmd_range(mm, pud, addr, next, fn, data); + if (err) + break; + } while (pud++, addr = next, addr != end); + return err; +} + +/* + * Scan a region of virtual memory, filling in page tables as necessary + * and calling a provided function on each leaf page table. + */ +int apply_to_page_range(struct mm_struct *mm, unsigned long addr, + unsigned long size, pte_fn_t fn, void *data) +{ + pgd_t *pgd; + unsigned long next; + unsigned long end = addr + size; + int err; + + BUG_ON(addr >= end); + pgd = pgd_offset(mm, addr); + do { + next = pgd_addr_end(addr, end); + err = apply_to_pud_range(mm, pgd, addr, next, fn, data); + if (err) + break; + } while (pgd++, addr = next, addr != end); + return err; +} +EXPORT_SYMBOL_GPL(apply_to_page_range); +#endif + /* * handle_pte_fault chooses page fault handler according to an entry * which was read non-atomically. Before making any commitment, on diff --git a/mm/mmap.c b/mm/mmap.c index c34750cf9..f6940d1b3 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -920,6 +920,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, if (!len) return -EINVAL; + error = arch_mmap_check(addr, len, flags); + if (error) + return error; + /* Careful about overflows.. */ len = PAGE_ALIGN(len); if (!len || len > TASK_SIZE) @@ -1940,6 +1944,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) unsigned long flags; struct rb_node ** rb_link, * rb_parent; pgoff_t pgoff = addr >> PAGE_SHIFT; + int error; len = PAGE_ALIGN(len); if (!len) @@ -1948,6 +1953,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if ((addr + len) > TASK_SIZE || (addr + len) < addr) return -EINVAL; + flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; + + error = arch_mmap_check(addr, len, flags); + if (error) + return error; + /* * mlock MCL_FUTURE? */ @@ -1991,8 +2002,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) !vx_vmpages_avail(mm, len >> PAGE_SHIFT)) return -ENOMEM; - flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; - /* Can we just expand an old private anonymous mapping? */ if (vma_merge(mm, prev, addr, addr + len, flags, NULL, NULL, pgoff, NULL)) @@ -2033,6 +2042,10 @@ void exit_mmap(struct mm_struct *mm) unsigned long nr_accounted = 0; unsigned long end; +#ifdef arch_exit_mmap + arch_exit_mmap(mm); +#endif + lru_add_drain(); flush_cache_mm(mm); tlb = tlb_gather_mmu(mm, 1); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b747cbf8b..5581dd1a4 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -439,7 +439,8 @@ static void __free_pages_ok(struct page *page, unsigned int order) int i; int reserved = 0; - arch_free_page(page, order); + if (arch_free_page(page, order)) + return; if (!PageHighMem(page)) mutex_debug_check_no_locks_freed(page_address(page), PAGE_SIZE<mapping = NULL; @@ -751,11 +753,6 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) if (pcp->count >= pcp->high) { free_pages_bulk(zone, pcp->batch, &pcp->list, 0); pcp->count -= pcp->batch; - } else if (zone->all_unreclaimable) { - spin_lock(&zone->lock); - zone->all_unreclaimable = 0; - zone->pages_scanned = 0; - spin_unlock(&zone->lock); } local_irq_restore(flags); put_cpu(); diff --git a/mm/pdflush.c b/mm/pdflush.c index c4b6d0afd..4842716d1 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c @@ -104,21 +104,20 @@ static int __pdflush(struct pdflush_work *my_work) list_move(&my_work->list, &pdflush_list); my_work->when_i_went_to_sleep = jiffies; spin_unlock_irq(&pdflush_lock); - schedule(); - if (try_to_freeze()) { - spin_lock_irq(&pdflush_lock); - continue; - } - + try_to_freeze(); spin_lock_irq(&pdflush_lock); if (!list_empty(&my_work->list)) { - printk("pdflush: bogus wakeup!\n"); + /* + * Someone woke us up, but without removing our control + * structure from the global list. swsusp will do this + * in try_to_freeze()->refrigerator(). Handle it. + */ my_work->fn = NULL; continue; } if (my_work->fn == NULL) { - printk("pdflush: NULL work function\n"); + printk("pdflush: bogus wakeup\n"); continue; } spin_unlock_irq(&pdflush_lock); diff --git a/mm/swapfile.c b/mm/swapfile.c index 234b2f173..a3bed3ff3 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -441,11 +441,12 @@ int swap_type_of(dev_t device) if (!(swap_info[i].flags & SWP_WRITEOK)) continue; + if (!device) { spin_unlock(&swap_lock); return i; } - inode = swap_info->swap_file->f_dentry->d_inode; + inode = swap_info[i].swap_file->f_dentry->d_inode; if (S_ISBLK(inode->i_mode) && device == MKDEV(imajor(inode), iminor(inode))) { spin_unlock(&swap_lock); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 3948949a6..729abc439 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -67,10 +67,6 @@ static struct packet_type vlan_packet_type = { .func = vlan_skb_recv, /* VLAN receive method */ }; -/* Bits of netdev state that are propagated from real device to virtual */ -#define VLAN_LINK_STATE_MASK \ - ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)|(1<<__LINK_STATE_DORMANT)) - /* End of global variables definitions. */ /* @@ -470,7 +466,9 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, new_dev->flags = real_dev->flags; new_dev->flags &= ~IFF_UP; - new_dev->state = real_dev->state & ~(1<<__LINK_STATE_START); + new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | + (1<<__LINK_STATE_DORMANT))) | + (1<<__LINK_STATE_PRESENT); /* need 4 bytes for extra VLAN header info, * hope the underlying device can handle it. diff --git a/net/atm/clip.c b/net/atm/clip.c index 72d852982..4f44e98f1 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -98,7 +98,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc); return; } - spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */ + netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */ entry->neigh->used = jiffies; for (walk = &entry->vccs; *walk; walk = &(*walk)->next) if (*walk == clip_vcc) { @@ -120,9 +120,9 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) goto out; } printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc " - "0x%p)\n", entry, clip_vcc); - out: - spin_unlock_bh(&entry->neigh->dev->xmit_lock); + "0x%p)\n",entry,clip_vcc); +out: + netif_tx_unlock_bh(entry->neigh->dev); } /* The neighbour entry n->lock is held. */ diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 0c88a2ac3..f8dbcee80 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -145,9 +145,9 @@ static int br_set_tx_csum(struct net_device *dev, u32 data) struct net_bridge *br = netdev_priv(dev); if (data) - br->feature_mask |= NETIF_F_IP_CSUM; + br->feature_mask |= NETIF_F_NO_CSUM; else - br->feature_mask &= ~NETIF_F_IP_CSUM; + br->feature_mask &= ~NETIF_F_ALL_CSUM; br_features_recompute(br); return 0; @@ -184,6 +184,6 @@ void br_dev_setup(struct net_device *dev) dev->set_mac_address = br_set_mac_address; dev->priv_flags = IFF_EBRIDGE; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST - | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM; + dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | + NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; } diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 56f3aa47e..056df7ceb 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -38,16 +38,20 @@ static inline unsigned packet_length(const struct sk_buff *skb) int br_dev_queue_push_xmit(struct sk_buff *skb) { /* drop mtu oversized packets except tso */ - if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size) + if (skb->len > skb->dev->mtu && !skb_is_gso(skb)) kfree_skb(skb); else { #ifdef CONFIG_BRIDGE_NETFILTER /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ - nf_bridge_maybe_copy_header(skb); + if (nf_bridge_maybe_copy_header(skb)) + kfree_skb(skb); + else #endif - skb_push(skb, ETH_HLEN); + { + skb_push(skb, ETH_HLEN); - dev_queue_xmit(skb); + dev_queue_xmit(skb); + } } return 0; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f5d47bf4f..f55ef682e 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -372,17 +372,28 @@ void br_features_recompute(struct net_bridge *br) struct net_bridge_port *p; unsigned long features, checksum; - features = br->feature_mask &~ NETIF_F_IP_CSUM; - checksum = br->feature_mask & NETIF_F_IP_CSUM; + checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; + features = br->feature_mask & ~NETIF_F_ALL_CSUM; list_for_each_entry(p, &br->port_list, list) { - if (!(p->dev->features - & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM))) + unsigned long feature = p->dev->features; + + if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) + checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; + if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) + checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; + if (!(feature & NETIF_F_IP_CSUM)) checksum = 0; - features &= p->dev->features; + + if (feature & NETIF_F_GSO) + feature |= NETIF_F_TSO; + feature |= NETIF_F_GSO; + + features &= feature; } - br->dev->features = features | checksum | NETIF_F_LLTX; + br->dev->features = features | checksum | NETIF_F_LLTX | + NETIF_F_GSO_ROBUST; } /* called with RTNL */ diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3da926444..a64272783 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -769,7 +769,7 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP) && skb->len > skb->dev->mtu && - !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) + !skb_is_gso(skb)) return ip_fragment(skb, br_dev_queue_push_xmit); else return br_dev_queue_push_xmit(skb); @@ -877,8 +877,9 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, struct sk_buff *skb = *pskb; if ((out->hard_start_xmit == br_dev_xmit && - okfn != br_nf_forward_finish && - okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit) + okfn != br_nf_forward_finish && + okfn != br_nf_local_out_finish && + okfn != br_nf_dev_queue_xmit) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) || ((out->priv_flags & IFF_802_1Q_VLAN) && VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index ee5a51761..ae70123c6 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -75,6 +75,9 @@ static void ulog_send(unsigned int nlgroup) if (timer_pending(&ub->timer)) del_timer(&ub->timer); + if (!ub->skb) + return; + /* last nlmsg needs NLMSG_DONE */ if (ub->qlen > 1) ub->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/net/core/dev.c b/net/core/dev.c index eb965a773..d8bab16e9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -115,8 +115,15 @@ #include #include #include +#include #include +#ifdef CONFIG_XEN +#include +#include +#include +#endif + /* * The list of packet types we will receive (as opposed to discard) * and the routines to invoke. @@ -1042,7 +1049,7 @@ static inline void net_timestamp(struct sk_buff *skb) * taps currently in use. */ -void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) +static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) { struct packet_type *ptype; @@ -1180,6 +1187,45 @@ out: return ret; } +/** + * skb_gso_segment - Perform segmentation on skb. + * @skb: buffer to segment + * @features: features for the output path (see dev->features) + * + * This function segments the given skb and returns a list of segments. + * + * It may return NULL if the skb requires no segmentation. This is + * only possible when GSO is used for verifying header integrity. + */ +struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); + struct packet_type *ptype; + int type = skb->protocol; + + BUG_ON(skb_shinfo(skb)->frag_list); + BUG_ON(skb->ip_summed != CHECKSUM_HW); + + skb->mac.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->data; + __skb_pull(skb, skb->mac_len); + + rcu_read_lock(); + list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { + if (ptype->type == type && !ptype->dev && ptype->gso_segment) { + segs = ptype->gso_segment(skb, features); + break; + } + } + rcu_read_unlock(); + + __skb_push(skb, skb->data - skb->mac.raw); + + return segs; +} + +EXPORT_SYMBOL(skb_gso_segment); + /* Take action when hardware reception checksum errors are detected. */ #ifdef CONFIG_BUG void netdev_rx_csum_fault(struct net_device *dev) @@ -1216,78 +1262,148 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) #define illegal_highdma(dev, skb) (0) #endif -/* Keep head the same: replace data */ -int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask) -{ - unsigned int size; - u8 *data; - long offset; - struct skb_shared_info *ninfo; - int headerlen = skb->data - skb->head; - int expand = (skb->tail + skb->data_len) - skb->end; - - if (skb_shared(skb)) - BUG(); - - if (expand <= 0) - expand = 0; - - size = skb->end - skb->head + expand; - size = SKB_DATA_ALIGN(size); - data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); - if (!data) - return -ENOMEM; - - /* Copy entire thing */ - if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len)) - BUG(); - - /* Set up shinfo */ - ninfo = (struct skb_shared_info*)(data + size); - atomic_set(&ninfo->dataref, 1); - ninfo->tso_size = skb_shinfo(skb)->tso_size; - ninfo->tso_segs = skb_shinfo(skb)->tso_segs; - ninfo->nr_frags = 0; - ninfo->frag_list = NULL; - - /* Offset between the two in bytes */ - offset = data - skb->head; - - /* Free old data. */ - skb_release_data(skb); - - skb->head = data; - skb->end = data + size; - - /* Set up new pointers */ - skb->h.raw += offset; - skb->nh.raw += offset; - skb->mac.raw += offset; - skb->tail += offset; - skb->data += offset; - - /* We are no longer a clone, even if we were. */ - skb->cloned = 0; - - skb->tail += skb->data_len; - skb->data_len = 0; +struct dev_gso_cb { + void (*destructor)(struct sk_buff *skb); +}; + +#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb) + +static void dev_gso_skb_destructor(struct sk_buff *skb) +{ + struct dev_gso_cb *cb; + + do { + struct sk_buff *nskb = skb->next; + + skb->next = nskb->next; + nskb->next = NULL; + kfree_skb(nskb); + } while (skb->next); + + cb = DEV_GSO_CB(skb); + if (cb->destructor) + cb->destructor(skb); +} + +/** + * dev_gso_segment - Perform emulated hardware segmentation on skb. + * @skb: buffer to segment + * + * This function segments the given skb and stores the list of segments + * in skb->next. + */ +static int dev_gso_segment(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + struct sk_buff *segs; + int features = dev->features & ~(illegal_highdma(dev, skb) ? + NETIF_F_SG : 0); + + segs = skb_gso_segment(skb, features); + + /* Verifying header integrity only. */ + if (!segs) + return 0; + + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + skb->next = segs; + DEV_GSO_CB(skb)->destructor = skb->destructor; + skb->destructor = dev_gso_skb_destructor; + + return 0; +} + +int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + if (likely(!skb->next)) { + if (netdev_nit) + dev_queue_xmit_nit(skb, dev); + + if (netif_needs_gso(dev, skb)) { + if (unlikely(dev_gso_segment(skb))) + goto out_kfree_skb; + if (skb->next) + goto gso; + } + + return dev->hard_start_xmit(skb, dev); + } + +gso: + do { + struct sk_buff *nskb = skb->next; + int rc; + + skb->next = nskb->next; + nskb->next = NULL; + rc = dev->hard_start_xmit(nskb, dev); + if (unlikely(rc)) { + nskb->next = skb->next; + skb->next = nskb; + return rc; + } + if (unlikely(netif_queue_stopped(dev) && skb->next)) + return NETDEV_TX_BUSY; + } while (skb->next); + + skb->destructor = DEV_GSO_CB(skb)->destructor; + +out_kfree_skb: + kfree_skb(skb); return 0; } #define HARD_TX_LOCK(dev, cpu) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ - spin_lock(&dev->xmit_lock); \ - dev->xmit_lock_owner = cpu; \ + netif_tx_lock(dev); \ } \ } #define HARD_TX_UNLOCK(dev) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ - dev->xmit_lock_owner = -1; \ - spin_unlock(&dev->xmit_lock); \ + netif_tx_unlock(dev); \ } \ } +#ifdef CONFIG_XEN +inline int skb_checksum_setup(struct sk_buff *skb) +{ + if (skb->proto_csum_blank) { + if (skb->protocol != htons(ETH_P_IP)) + goto out; + skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl; + if (skb->h.raw >= skb->tail) + goto out; + switch (skb->nh.iph->protocol) { + case IPPROTO_TCP: + skb->csum = offsetof(struct tcphdr, check); + break; + case IPPROTO_UDP: + skb->csum = offsetof(struct udphdr, check); + break; + default: + if (net_ratelimit()) + printk(KERN_ERR "Attempting to checksum a non-" + "TCP/UDP packet, dropping a protocol" + " %d packet", skb->nh.iph->protocol); + goto out; + } + if ((skb->h.raw + skb->csum + 2) > skb->tail) + goto out; + skb->ip_summed = CHECKSUM_HW; + skb->proto_csum_blank = 0; + } + return 0; +out: + return -EPROTO; +} +#else +inline int skb_checksum_setup(struct sk_buff *skb) { return 0; } +#endif + + /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -1320,9 +1436,19 @@ int dev_queue_xmit(struct sk_buff *skb) struct Qdisc *q; int rc = -ENOMEM; + /* If a checksum-deferred packet is forwarded to a device that needs a + * checksum, correct the pointers and force checksumming. + */ + if (skb_checksum_setup(skb)) + goto out_kfree_skb; + + /* GSO will handle the following emulations directly. */ + if (netif_needs_gso(dev, skb)) + goto gso; + if (skb_shinfo(skb)->frag_list && !(dev->features & NETIF_F_FRAGLIST) && - __skb_linearize(skb, GFP_ATOMIC)) + __skb_linearize(skb)) goto out_kfree_skb; /* Fragmented skb is linearized if device does not support SG, @@ -1331,25 +1457,26 @@ int dev_queue_xmit(struct sk_buff *skb) */ if (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && - __skb_linearize(skb, GFP_ATOMIC)) + __skb_linearize(skb)) goto out_kfree_skb; /* If packet is not checksummed and device does not support * checksumming for this protocol, complete checksumming here. */ if (skb->ip_summed == CHECKSUM_HW && - (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) && + (!(dev->features & NETIF_F_GEN_CSUM) && (!(dev->features & NETIF_F_IP_CSUM) || skb->protocol != htons(ETH_P_IP)))) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; +gso: spin_lock_prefetch(&dev->queue_lock); /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ - local_bh_disable(); + rcu_read_lock_bh(); /* Updates of qdisc are serialized by queue_lock. * The struct Qdisc which is pointed to by qdisc is now a @@ -1383,8 +1510,8 @@ int dev_queue_xmit(struct sk_buff *skb) /* The device has no queue. Common case for software devices: loopback, all the sorts of tunnels... - Really, it is unlikely that xmit_lock protection is necessary here. - (f.e. loopback and IP tunnels are clean ignoring statistics + Really, it is unlikely that netif_tx_lock protection is necessary + here. (f.e. loopback and IP tunnels are clean ignoring statistics counters.) However, it is possible, that they rely on protection made by us here. @@ -1400,11 +1527,8 @@ int dev_queue_xmit(struct sk_buff *skb) HARD_TX_LOCK(dev, cpu); if (!netif_queue_stopped(dev)) { - if (netdev_nit) - dev_queue_xmit_nit(skb, dev); - rc = 0; - if (!dev->hard_start_xmit(skb, dev)) { + if (!dev_hard_start_xmit(skb, dev)) { HARD_TX_UNLOCK(dev); goto out; } @@ -1423,13 +1547,13 @@ int dev_queue_xmit(struct sk_buff *skb) } rc = -ENETDOWN; - local_bh_enable(); + rcu_read_unlock_bh(); out_kfree_skb: kfree_skb(skb); return rc; out: - local_bh_enable(); + rcu_read_unlock_bh(); return rc; } @@ -1707,6 +1831,19 @@ int netif_receive_skb(struct sk_buff *skb) } #endif +#ifdef CONFIG_XEN + switch (skb->ip_summed) { + case CHECKSUM_UNNECESSARY: + skb->proto_data_valid = 1; + break; + case CHECKSUM_HW: + /* XXX Implement me. */ + default: + skb->proto_data_valid = 0; + break; + } +#endif + list_for_each_entry_rcu(ptype, &ptype_all, list) { if (!ptype->dev || ptype->dev == skb->dev) { if (pt_prev) @@ -2793,7 +2930,7 @@ int register_netdevice(struct net_device *dev) BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); spin_lock_init(&dev->queue_lock); - spin_lock_init(&dev->xmit_lock); + spin_lock_init(&dev->_xmit_lock); dev->xmit_lock_owner = -1; #ifdef CONFIG_NET_CLS_ACT spin_lock_init(&dev->ingress_lock); @@ -2837,9 +2974,7 @@ int register_netdevice(struct net_device *dev) /* Fix illegal SG+CSUM combinations. */ if ((dev->features & NETIF_F_SG) && - !(dev->features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) { + !(dev->features & NETIF_F_ALL_CSUM)) { printk("%s: Dropping NETIF_F_SG since no checksum feature.\n", dev->name); dev->features &= ~NETIF_F_SG; @@ -3379,7 +3514,6 @@ subsys_initcall(net_dev_init); EXPORT_SYMBOL(__dev_get_by_index); EXPORT_SYMBOL(__dev_get_by_name); EXPORT_SYMBOL(__dev_remove_pack); -EXPORT_SYMBOL(__skb_linearize); EXPORT_SYMBOL(dev_valid_name); EXPORT_SYMBOL(dev_add_pack); EXPORT_SYMBOL(dev_alloc_name); @@ -3411,6 +3545,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier); EXPORT_SYMBOL(net_enable_timestamp); EXPORT_SYMBOL(net_disable_timestamp); EXPORT_SYMBOL(dev_get_flags); +EXPORT_SYMBOL(skb_checksum_setup); #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) EXPORT_SYMBOL(br_handle_frame_hook); diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 05d608508..c57d887da 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -62,7 +62,7 @@ * Device mc lists are changed by bh at least if IPv6 is enabled, * so that it must be bh protected. * - * We block accesses to device mc filters with dev->xmit_lock. + * We block accesses to device mc filters with netif_tx_lock. */ /* @@ -93,9 +93,9 @@ static void __dev_mc_upload(struct net_device *dev) void dev_mc_upload(struct net_device *dev) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); __dev_mc_upload(dev); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } /* @@ -107,7 +107,7 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) int err = 0; struct dev_mc_list *dmi, **dmip; - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { /* @@ -139,13 +139,13 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) */ __dev_mc_upload(dev); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; } } err = -ENOENT; done: - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return err; } @@ -160,7 +160,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && dmi->dmi_addrlen == alen) { @@ -176,7 +176,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) } if ((dmi = dmi1) == NULL) { - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return -ENOMEM; } memcpy(dmi->dmi_addr, addr, alen); @@ -189,11 +189,11 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) __dev_mc_upload(dev); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; done: - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); kfree(dmi1); return err; } @@ -204,7 +204,7 @@ done: void dev_mc_discard(struct net_device *dev) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); while (dev->mc_list != NULL) { struct dev_mc_list *tmp = dev->mc_list; @@ -215,7 +215,7 @@ void dev_mc_discard(struct net_device *dev) } dev->mc_count = 0; - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } #ifdef CONFIG_PROC_FS @@ -250,7 +250,7 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v) struct dev_mc_list *m; struct net_device *dev = v; - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); for (m = dev->mc_list; m; m = m->next) { int i; @@ -262,7 +262,7 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v) seq_putc(seq, '\n'); } - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; } diff --git a/net/core/dst.c b/net/core/dst.c index 470c05bc4..1a5e49da0 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -95,12 +95,11 @@ static void dst_run_gc(unsigned long dummy) dst_gc_timer_inc = DST_GC_INC; dst_gc_timer_expires = DST_GC_MIN; } - dst_gc_timer.expires = jiffies + dst_gc_timer_expires; #if RT_CACHE_DEBUG >= 2 printk("dst_total: %d/%d %ld\n", atomic_read(&dst_total), delayed, dst_gc_timer_expires); #endif - add_timer(&dst_gc_timer); + mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires); out: spin_unlock(&dst_lock); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index c680b7e04..987cccaa0 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -30,7 +30,7 @@ u32 ethtool_op_get_link(struct net_device *dev) u32 ethtool_op_get_tx_csum(struct net_device *dev) { - return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0; + return (dev->features & NETIF_F_ALL_CSUM) != 0; } int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) @@ -437,7 +437,7 @@ static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr) { struct ethtool_pauseparam pauseparam; - if (!dev->ethtool_ops->get_pauseparam) + if (!dev->ethtool_ops->set_pauseparam) return -EOPNOTSUPP; if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) @@ -551,9 +551,7 @@ static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) return -EFAULT; if (edata.data && - !(dev->features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) + !(dev->features & NETIF_F_ALL_CSUM)) return -EINVAL; return __ethtool_set_sg(dev, edata.data); @@ -561,7 +559,7 @@ static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) static int ethtool_get_tso(struct net_device *dev, char __user *useraddr) { - struct ethtool_value edata = { ETHTOOL_GTSO }; + struct ethtool_value edata = { ETHTOOL_GUFO }; if (!dev->ethtool_ops->get_tso) return -EOPNOTSUPP; @@ -616,6 +614,29 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) return dev->ethtool_ops->set_ufo(dev, edata.data); } +static int ethtool_get_gso(struct net_device *dev, char __user *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GGSO }; + + edata.data = dev->features & NETIF_F_GSO; + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_gso(struct net_device *dev, char __user *useraddr) +{ + struct ethtool_value edata; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + if (edata.data) + dev->features |= NETIF_F_GSO; + else + dev->features &= ~NETIF_F_GSO; + return 0; +} + static int ethtool_self_test(struct net_device *dev, char __user *useraddr) { struct ethtool_test test; @@ -907,6 +928,12 @@ int dev_ethtool(struct ifreq *ifr) case ETHTOOL_SUFO: rc = ethtool_set_ufo(dev, useraddr); break; + case ETHTOOL_GGSO: + rc = ethtool_get_gso(dev, useraddr); + break; + case ETHTOOL_SGSO: + rc = ethtool_set_gso(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e8e05cebd..9cb781830 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -273,24 +273,21 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) do { npinfo->tries--; - spin_lock(&np->dev->xmit_lock); - np->dev->xmit_lock_owner = smp_processor_id(); + netif_tx_lock(np->dev); /* * network drivers do not expect to be called if the queue is * stopped. */ if (netif_queue_stopped(np->dev)) { - np->dev->xmit_lock_owner = -1; - spin_unlock(&np->dev->xmit_lock); + netif_tx_unlock(np->dev); netpoll_poll(np); udelay(50); continue; } status = np->dev->hard_start_xmit(skb, np->dev); - np->dev->xmit_lock_owner = -1; - spin_unlock(&np->dev->xmit_lock); + netif_tx_unlock(np->dev); /* success */ if(!status) { diff --git a/net/core/pktgen.c b/net/core/pktgen.c index c23e9c06e..4e7437a56 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2149,6 +2149,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); skb->dev = odev; skb->pkt_type = PACKET_HOST; + skb->nh.iph = iph; + skb->h.uh = udph; if (pkt_dev->nfrags <= 0) pgh = (struct pktgen_hdr *)skb_put(skb, datalen); @@ -2460,6 +2462,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, skb->protocol = protocol; skb->dev = odev; skb->pkt_type = PACKET_HOST; + skb->nh.ipv6h = iph; + skb->h.uh = udph; if (pkt_dev->nfrags <= 0) pgh = (struct pktgen_hdr *)skb_put(skb, datalen); @@ -2896,8 +2900,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) pkt_dev->clone_count = 0; /* reset counter */ } } - - spin_lock_bh(&odev->xmit_lock); + + netif_tx_lock_bh(odev); if (!netif_queue_stopped(odev)) { atomic_inc(&(pkt_dev->skb->users)); @@ -2942,8 +2946,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) pkt_dev->next_tx_ns = 0; } - spin_unlock_bh(&odev->xmit_lock); - + netif_tx_unlock_bh(odev); + /* If pkt_dev->count is zero, then run forever */ if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { if (atomic_read(&(pkt_dev->skb->users)) != 1) { diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index cfd2d1ef8..375dd9061 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -398,6 +398,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) } if (ida[IFLA_ADDRESS - 1]) { + struct sockaddr *sa; + int len; + if (!dev->set_mac_address) { err = -EOPNOTSUPP; goto out; @@ -409,7 +412,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) goto out; - err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1])); + len = sizeof(sa_family_t) + dev->addr_len; + sa = kmalloc(len, GFP_KERNEL); + if (!sa) { + err = -ENOMEM; + goto out; + } + sa->sa_family = dev->type; + memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]), + dev->addr_len); + err = dev->set_mac_address(dev, sa); + kfree(sa); if (err) goto out; send_addr_notify = 1; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fb3770f9c..bd64cb46f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -140,6 +140,7 @@ EXPORT_SYMBOL(skb_truesize_bug); * Buffers may only be allocated from interrupts using a @gfp_mask of * %GFP_ATOMIC. */ +#ifndef CONFIG_HAVE_ARCH_ALLOC_SKB struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone) { @@ -172,9 +173,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, shinfo = skb_shinfo(skb); atomic_set(&shinfo->dataref, 1); shinfo->nr_frags = 0; - shinfo->tso_size = 0; - shinfo->tso_segs = 0; - shinfo->ufo_size = 0; + shinfo->gso_size = 0; + shinfo->gso_segs = 0; + shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; shinfo->frag_list = NULL; @@ -194,6 +195,7 @@ nodata: skb = NULL; goto out; } +#endif /* !CONFIG_HAVE_ARCH_ALLOC_SKB */ /** * alloc_skb_from_cache - allocate a network buffer @@ -211,14 +213,18 @@ nodata: */ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, unsigned int size, - gfp_t gfp_mask) + gfp_t gfp_mask, + int fclone) { + kmem_cache_t *cache; + struct skb_shared_info *shinfo; struct sk_buff *skb; u8 *data; + cache = fclone ? skbuff_fclone_cache : skbuff_head_cache; + /* Get the HEAD */ - skb = kmem_cache_alloc(skbuff_head_cache, - gfp_mask & ~__GFP_DMA); + skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA); if (!skb) goto out; @@ -235,26 +241,39 @@ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, skb->data = data; skb->tail = data; skb->end = data + size; + /* make sure we initialize shinfo sequentially */ + shinfo = skb_shinfo(skb); + atomic_set(&shinfo->dataref, 1); + shinfo->nr_frags = 0; + shinfo->gso_size = 0; + shinfo->gso_segs = 0; + shinfo->gso_type = 0; + shinfo->ip6_frag_id = 0; + shinfo->frag_list = NULL; - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->tso_size = 0; - skb_shinfo(skb)->tso_segs = 0; - skb_shinfo(skb)->frag_list = NULL; + if (fclone) { + struct sk_buff *child = skb + 1; + atomic_t *fclone_ref = (atomic_t *) (child + 1); + + skb->fclone = SKB_FCLONE_ORIG; + atomic_set(fclone_ref, 1); + + child->fclone = SKB_FCLONE_UNAVAILABLE; + } out: return skb; nodata: - kmem_cache_free(skbuff_head_cache, skb); + kmem_cache_free(cache, skb); skb = NULL; goto out; } -static void skb_drop_fraglist(struct sk_buff *skb) +static void skb_drop_list(struct sk_buff **listp) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + struct sk_buff *list = *listp; - skb_shinfo(skb)->frag_list = NULL; + *listp = NULL; do { struct sk_buff *this = list; @@ -263,6 +282,11 @@ static void skb_drop_fraglist(struct sk_buff *skb) } while (list); } +static inline void skb_drop_fraglist(struct sk_buff *skb) +{ + skb_drop_list(&skb_shinfo(skb)->frag_list); +} + static void skb_clone_fraglist(struct sk_buff *skb) { struct sk_buff *list; @@ -434,6 +458,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) C(local_df); n->cloned = 1; n->nohdr = 0; +#ifdef CONFIG_XEN + C(proto_data_valid); + C(proto_csum_blank); +#endif C(pkt_type); C(ip_summed); C(priority); @@ -527,8 +555,9 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->tc_index = old->tc_index; #endif atomic_set(&new->users, 1); - skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size; - skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs; + skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; + skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; + skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; } /** @@ -800,49 +829,86 @@ struct sk_buff *skb_pad(struct sk_buff *skb, int pad) return nskb; } -/* Trims skb to length len. It can change skb pointers, if "realloc" is 1. - * If realloc==0 and trimming is impossible without change of data, - * it is BUG(). +/* Trims skb to length len. It can change skb pointers. */ -int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc) +int ___pskb_trim(struct sk_buff *skb, unsigned int len) { + struct sk_buff **fragp; + struct sk_buff *frag; int offset = skb_headlen(skb); int nfrags = skb_shinfo(skb)->nr_frags; int i; + int err; - for (i = 0; i < nfrags; i++) { + if (skb_cloned(skb) && + unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) + return err; + + i = 0; + if (offset >= len) + goto drop_pages; + + for (; i < nfrags; i++) { int end = offset + skb_shinfo(skb)->frags[i].size; - if (end > len) { - if (skb_cloned(skb)) { - BUG_ON(!realloc); - if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - return -ENOMEM; - } - if (len <= offset) { - put_page(skb_shinfo(skb)->frags[i].page); - skb_shinfo(skb)->nr_frags--; - } else { - skb_shinfo(skb)->frags[i].size = len - offset; - } + + if (end < len) { + offset = end; + continue; } - offset = end; + + skb_shinfo(skb)->frags[i++].size = len - offset; + +drop_pages: + skb_shinfo(skb)->nr_frags = i; + + for (; i < nfrags; i++) + put_page(skb_shinfo(skb)->frags[i].page); + + if (skb_shinfo(skb)->frag_list) + skb_drop_fraglist(skb); + goto done; } - if (offset < len) { + for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); + fragp = &frag->next) { + int end = offset + frag->len; + + if (skb_shared(frag)) { + struct sk_buff *nfrag; + + nfrag = skb_clone(frag, GFP_ATOMIC); + if (unlikely(!nfrag)) + return -ENOMEM; + + nfrag->next = frag->next; + kfree_skb(frag); + frag = nfrag; + *fragp = frag; + } + + if (end < len) { + offset = end; + continue; + } + + if (end > len && + unlikely((err = pskb_trim(frag, len - offset)))) + return err; + + if (frag->next) + skb_drop_list(&frag->next); + break; + } + +done: + if (len > skb_headlen(skb)) { skb->data_len -= skb->len - len; skb->len = len; } else { - if (len <= skb_headlen(skb)) { - skb->len = len; - skb->data_len = 0; - skb->tail = skb->data + len; - if (skb_shinfo(skb)->frag_list && !skb_cloned(skb)) - skb_drop_fraglist(skb); - } else { - skb->data_len -= skb->len - len; - skb->len = len; - } + skb->len = len; + skb->data_len = 0; + skb->tail = skb->data + len; } return 0; @@ -1826,6 +1892,133 @@ unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) EXPORT_SYMBOL_GPL(skb_pull_rcsum); +/** + * skb_segment - Perform protocol segmentation on skb. + * @skb: buffer to segment + * @features: features for the output path (see dev->features) + * + * This function performs segmentation on the given skb. It returns + * the segment at the given position. It returns NULL if there are + * no more segments to generate, or when an error is encountered. + */ +struct sk_buff *skb_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = NULL; + struct sk_buff *tail = NULL; + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int doffset = skb->data - skb->mac.raw; + unsigned int offset = doffset; + unsigned int headroom; + unsigned int len; + int sg = features & NETIF_F_SG; + int nfrags = skb_shinfo(skb)->nr_frags; + int err = -ENOMEM; + int i = 0; + int pos; + + __skb_push(skb, doffset); + headroom = skb_headroom(skb); + pos = skb_headlen(skb); + + do { + struct sk_buff *nskb; + skb_frag_t *frag; + int hsize, nsize; + int k; + int size; + + len = skb->len - offset; + if (len > mss) + len = mss; + + hsize = skb_headlen(skb) - offset; + if (hsize < 0) + hsize = 0; + nsize = hsize + doffset; + if (nsize > len + doffset || !sg) + nsize = len + doffset; + + nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); + if (unlikely(!nskb)) + goto err; + + if (segs) + tail->next = nskb; + else + segs = nskb; + tail = nskb; + + nskb->dev = skb->dev; + nskb->priority = skb->priority; + nskb->protocol = skb->protocol; + nskb->dst = dst_clone(skb->dst); + memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); + nskb->pkt_type = skb->pkt_type; + nskb->mac_len = skb->mac_len; + + skb_reserve(nskb, headroom); + nskb->mac.raw = nskb->data; + nskb->nh.raw = nskb->data + skb->mac_len; + nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw); + memcpy(skb_put(nskb, doffset), skb->data, doffset); + + if (!sg) { + nskb->csum = skb_copy_and_csum_bits(skb, offset, + skb_put(nskb, len), + len, 0); + continue; + } + + frag = skb_shinfo(nskb)->frags; + k = 0; + + nskb->ip_summed = CHECKSUM_HW; + nskb->csum = skb->csum; + memcpy(skb_put(nskb, hsize), skb->data + offset, hsize); + + while (pos < offset + len) { + BUG_ON(i >= nfrags); + + *frag = skb_shinfo(skb)->frags[i]; + get_page(frag->page); + size = frag->size; + + if (pos < offset) { + frag->page_offset += offset - pos; + frag->size -= offset - pos; + } + + k++; + + if (pos + size <= offset + len) { + i++; + pos += size; + } else { + frag->size -= pos + size - (offset + len); + break; + } + + frag++; + } + + skb_shinfo(nskb)->nr_frags = k; + nskb->data_len = len - hsize; + nskb->len += nskb->data_len; + nskb->truesize += nskb->data_len; + } while ((offset += len) < skb->len); + + return segs; + +err: + while ((skb = segs)) { + segs = skb->next; + kfree(skb); + } + return ERR_PTR(err); +} + +EXPORT_SYMBOL_GPL(skb_segment); + void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 547523b41..a2ba9db1c 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -801,8 +801,7 @@ got_it: * We linearize everything except data segments here. */ if (cb->nsp_flags & ~0x60) { - if (unlikely(skb_is_nonlinear(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) + if (unlikely(skb_linearize(skb))) goto free_out; } diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index e172cf98d..5abf7057a 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -629,8 +629,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type padlen); if (flags & DN_RT_PKT_CNTL) { - if (unlikely(skb_is_nonlinear(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) + if (unlikely(skb_linearize(skb))) goto dump_it; switch(flags & DN_RT_CNTL_MSK) { diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 446faafe2..2440d0504 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -400,9 +400,10 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) { if (idx < s_idx) - continue; + goto next; if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) break; +next: idx++; } rcu_read_unlock(); diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index dbb08528d..f7e84e9d1 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig @@ -58,6 +58,7 @@ config IEEE80211_CRYPT_TKIP depends on IEEE80211 && NET_RADIO select CRYPTO select CRYPTO_MICHAEL_MIC + select CRC32 ---help--- Include software based cipher suites in support of IEEE 802.11i (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index ccf85aa4b..f4f4aa6e7 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -68,6 +68,7 @@ */ #include +#include #include #include #include @@ -1137,6 +1138,88 @@ int inet_sk_rebuild_header(struct sock *sk) EXPORT_SYMBOL(inet_sk_rebuild_header); +static int inet_gso_send_check(struct sk_buff *skb) +{ + struct iphdr *iph; + struct net_protocol *ops; + int proto; + int ihl; + int err = -EINVAL; + + if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) + goto out; + + iph = skb->nh.iph; + ihl = iph->ihl * 4; + if (ihl < sizeof(*iph)) + goto out; + + if (unlikely(!pskb_may_pull(skb, ihl))) + goto out; + + skb->h.raw = __skb_pull(skb, ihl); + iph = skb->nh.iph; + proto = iph->protocol & (MAX_INET_PROTOS - 1); + err = -EPROTONOSUPPORT; + + rcu_read_lock(); + ops = rcu_dereference(inet_protos[proto]); + if (likely(ops && ops->gso_send_check)) + err = ops->gso_send_check(skb); + rcu_read_unlock(); + +out: + return err; +} + +static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct iphdr *iph; + struct net_protocol *ops; + int proto; + int ihl; + int id; + + if (!pskb_may_pull(skb, sizeof(*iph))) + goto out; + + iph = skb->nh.iph; + ihl = iph->ihl * 4; + if (ihl < sizeof(*iph)) + goto out; + + if (!pskb_may_pull(skb, ihl)) + goto out; + + skb->h.raw = __skb_pull(skb, ihl); + iph = skb->nh.iph; + id = ntohs(iph->id); + proto = iph->protocol & (MAX_INET_PROTOS - 1); + segs = ERR_PTR(-EPROTONOSUPPORT); + + rcu_read_lock(); + ops = rcu_dereference(inet_protos[proto]); + if (ops && ops->gso_segment) + segs = ops->gso_segment(skb, features); + rcu_read_unlock(); + + if (!segs || unlikely(IS_ERR(segs))) + goto out; + + skb = segs; + do { + iph = skb->nh.iph; + iph->id = htons(id++); + iph->tot_len = htons(skb->len - skb->mac_len); + iph->check = 0; + iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); + } while ((skb = skb->next)); + +out: + return segs; +} + #ifdef CONFIG_IP_MULTICAST static struct net_protocol igmp_protocol = { .handler = igmp_rcv, @@ -1146,6 +1229,8 @@ static struct net_protocol igmp_protocol = { static struct net_protocol tcp_protocol = { .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, + .gso_send_check = tcp_v4_gso_send_check, + .gso_segment = tcp_tso_segment, .no_policy = 1, }; @@ -1191,6 +1276,8 @@ static int ipv4_proc_init(void); static struct packet_type ip_packet_type = { .type = __constant_htons(ETH_P_IP), .func = ip_rcv, + .gso_send_check = inet_gso_send_check, + .gso_segment = inet_gso_segment, }; static int __init inet_init(void) diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index ec566f3e6..a66c96a25 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -458,13 +458,13 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); hlist_for_each_entry(r, node, &fib_rules, hlist) { - if (idx < s_idx) - continue; + goto next; if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, NLM_F_MULTI) < 0) break; +next: idx++; } rcu_read_unlock(); diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 0f4145bab..1de08c186 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -160,7 +160,7 @@ void free_fib_info(struct fib_info *fi) void fib_release_info(struct fib_info *fi) { - write_lock(&fib_info_lock); + write_lock_bh(&fib_info_lock); if (fi && --fi->fib_treeref == 0) { hlist_del(&fi->fib_hash); if (fi->fib_prefsrc) @@ -173,7 +173,7 @@ void fib_release_info(struct fib_info *fi) fi->fib_dead = 1; fib_info_put(fi); } - write_unlock(&fib_info_lock); + write_unlock_bh(&fib_info_lock); } static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) @@ -599,7 +599,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, unsigned int old_size = fib_hash_size; unsigned int i, bytes; - write_lock(&fib_info_lock); + write_lock_bh(&fib_info_lock); old_info_hash = fib_info_hash; old_laddrhash = fib_info_laddrhash; fib_hash_size = new_size; @@ -640,7 +640,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, } fib_info_laddrhash = new_laddrhash; - write_unlock(&fib_info_lock); + write_unlock_bh(&fib_info_lock); bytes = old_size * sizeof(struct hlist_head *); fib_hash_free(old_info_hash, bytes); @@ -822,7 +822,7 @@ link_it: fi->fib_treeref++; atomic_inc(&fi->fib_clntref); - write_lock(&fib_info_lock); + write_lock_bh(&fib_info_lock); hlist_add_head(&fi->fib_hash, &fib_info_hash[fib_info_hashfn(fi)]); if (fi->fib_prefsrc) { @@ -841,7 +841,7 @@ link_it: head = &fib_info_devhash[hash]; hlist_add_head(&nh->nh_hash, head); } endfor_nexthops(fi) - write_unlock(&fib_info_lock); + write_unlock_bh(&fib_info_lock); return fi; err_inval: diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index cff9c3a72..20b17047c 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -210,8 +210,7 @@ static inline int ip_finish_output(struct sk_buff *skb) return dst_output(skb); } #endif - if (skb->len > dst_mtu(skb->dst) && - !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) + if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) return ip_fragment(skb, ip_finish_output2); else return ip_finish_output2(skb); @@ -362,7 +361,7 @@ packet_routed: } ip_select_ident_more(iph, &rt->u.dst, sk, - (skb_shinfo(skb)->tso_segs ?: 1) - 1); + (skb_shinfo(skb)->gso_segs ?: 1) - 1); /* Add an IP checksum. */ ip_send_check(iph); @@ -743,7 +742,8 @@ static inline int ip_ufo_append_data(struct sock *sk, (length - transhdrlen)); if (!err) { /* specify the length of each IP datagram fragment*/ - skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); + skb_shinfo(skb)->gso_size = mtu - fragheaderlen; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; __skb_queue_tail(&sk->sk_write_queue, skb); return 0; @@ -839,7 +839,7 @@ int ip_append_data(struct sock *sk, */ if (transhdrlen && length + fragheaderlen <= mtu && - rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) && + rt->u.dst.dev->features & NETIF_F_ALL_CSUM && !exthdrlen) csummode = CHECKSUM_HW; @@ -946,7 +946,7 @@ alloc_new_skb: skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; - skb_trim(skb_prev, maxfraglen); + pskb_trim_unique(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; @@ -1086,14 +1086,16 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, inet->cork.length += size; if ((sk->sk_protocol == IPPROTO_UDP) && - (rt->u.dst.dev->features & NETIF_F_UFO)) - skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); + (rt->u.dst.dev->features & NETIF_F_UFO)) { + skb_shinfo(skb)->gso_size = mtu - fragheaderlen; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; + } while (size > 0) { int i; - if (skb_shinfo(skb)->ufo_size) + if (skb_is_gso(skb)) len = size; else { @@ -1139,7 +1141,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, data, fraggap, 0); skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); - skb_trim(skb_prev, maxfraglen); + pskb_trim_unique(skb_prev, maxfraglen); } /* diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 95278b22b..098d103ec 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -84,7 +84,7 @@ out: static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) { u8 nexthdr; - int err = 0; + int err = -ENOMEM; struct iphdr *iph; union { struct iphdr iph; @@ -92,11 +92,8 @@ static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) } tmp_iph; - if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) { - err = -ENOMEM; + if (skb_linearize_cow(skb)) goto out; - } skb->ip_summed = CHECKSUM_NONE; @@ -171,10 +168,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb) goto out_ok; } - if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) { + if (skb_linearize_cow(skb)) goto out_ok; - } err = ipcomp_compress(x, skb); iph = skb->nh.iph; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index d0d191920..92adfebec 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -237,7 +237,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, struct arpt_entry *e, *back; const char *indev, *outdev; void *table_base; - struct xt_table_info *private = table->private; + struct xt_table_info *private; /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + @@ -249,6 +249,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, outdev = out ? out->name : nulldevname; read_lock_bh(&table->lock); + private = table->private; table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); back = get_entry(table_base, private->underflow[hook]); diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index 518f581d3..853a3d512 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -1092,7 +1092,7 @@ static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct, tuple.dst.protonum = IPPROTO_TCP; exp = __ip_conntrack_expect_find(&tuple); - if (exp->master == ct) + if (exp && exp->master == ct) return exp; return NULL; } diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index a3d14079e..35d1d90c9 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb, if (hdrsize < sizeof(*hdr)) return 1; - hdr->check = ip_nat_cheat_check(~oldip, newip, +#ifdef CONFIG_XEN + if ((*pskb)->proto_csum_blank) + hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check); + else +#endif + hdr->check = ip_nat_cheat_check(~oldip, newip, ip_nat_cheat_check(oldport ^ 0xFFFF, newport, hdr->check)); diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index ec6053fdc..e8eaf6a37 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb, newport = tuple->dst.u.udp.port; portptr = &hdr->dest; } - if (hdr->check) /* 0 is a special case meaning no checksum */ - hdr->check = ip_nat_cheat_check(~oldip, newip, + if (hdr->check) { /* 0 is a special case meaning no checksum */ +#ifdef CONFIG_XEN + if ((*pskb)->proto_csum_blank) + hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check); + else +#endif + hdr->check = ip_nat_cheat_check(~oldip, newip, ip_nat_cheat_check(*portptr ^ 0xFFFF, newport, hdr->check)); + } *portptr = newport; return 1; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index cee3397ec..71871c4f9 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -231,7 +231,7 @@ ipt_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ipt_entry *e, *back; - struct xt_table_info *private = table->private; + struct xt_table_info *private; /* Initialization */ ip = (*pskb)->nh.iph; @@ -248,6 +248,7 @@ ipt_do_table(struct sk_buff **pskb, read_lock_bh(&table->lock); IP_NF_ASSERT(table->valid_hooks & (1 << hook)); + private = table->private; table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index c84cc0338..090f138e7 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -116,6 +116,11 @@ static void ulog_send(unsigned int nlgroupnum) del_timer(&ub->timer); } + if (!ub->skb) { + DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); + return; + } + /* last nlmsg needs NLMSG_DONE */ if (ub->qlen > 1) ub->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cc9423de7..5fe2fcf99 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -3144,7 +3144,7 @@ int __init ip_rt_init(void) rhash_entries, (num_physpages >= 128 * 1024) ? 15 : 17, - HASH_HIGHMEM, + 0, &rt_hash_log, &rt_hash_mask, 0); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 6a228319f..e369c0b9d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -258,6 +258,7 @@ #include #include #include +#include #include #include @@ -572,7 +573,7 @@ new_segment: skb->ip_summed = CHECKSUM_HW; tp->write_seq += copy; TCP_SKB_CB(skb)->end_seq += copy; - skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->gso_segs = 0; if (!copied) TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH; @@ -623,14 +624,10 @@ ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, ssize_t res; struct sock *sk = sock->sk; -#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) - if (!(sk->sk_route_caps & NETIF_F_SG) || - !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS)) + !(sk->sk_route_caps & NETIF_F_ALL_CSUM)) return sock_no_sendpage(sock, page, offset, size, flags); -#undef TCP_ZC_CSUM_FLAGS - lock_sock(sk); TCP_CHECK_TIMER(sk); res = do_tcp_sendpages(sk, &page, offset, size, flags); @@ -727,9 +724,7 @@ new_segment: /* * Check whether we can use HW checksum. */ - if (sk->sk_route_caps & - (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM)) + if (sk->sk_route_caps & NETIF_F_ALL_CSUM) skb->ip_summed = CHECKSUM_HW; skb_entail(sk, tp, skb); @@ -825,7 +820,7 @@ new_segment: tp->write_seq += copy; TCP_SKB_CB(skb)->end_seq += copy; - skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->gso_segs = 0; from += copy; copied += copy; @@ -2072,6 +2067,77 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL(compat_tcp_getsockopt); #endif +struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct tcphdr *th; + unsigned thlen; + unsigned int seq; + unsigned int delta; + unsigned int oldlen; + unsigned int len; + + if (!pskb_may_pull(skb, sizeof(*th))) + goto out; + + th = skb->h.th; + thlen = th->doff * 4; + if (thlen < sizeof(*th)) + goto out; + + if (!pskb_may_pull(skb, thlen)) + goto out; + + oldlen = (u16)~skb->len; + __skb_pull(skb, thlen); + + if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { + /* Packet is from an untrusted source, reset gso_segs. */ + int mss = skb_shinfo(skb)->gso_size; + + skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; + + segs = NULL; + goto out; + } + + segs = skb_segment(skb, features); + if (IS_ERR(segs)) + goto out; + + len = skb_shinfo(skb)->gso_size; + delta = htonl(oldlen + (thlen + len)); + + skb = segs; + th = skb->h.th; + seq = ntohl(th->seq); + + do { + th->fin = th->psh = 0; + + th->check = ~csum_fold(th->check + delta); + if (skb->ip_summed != CHECKSUM_HW) + th->check = csum_fold(csum_partial(skb->h.raw, thlen, + skb->csum)); + + seq += len; + skb = skb->next; + th = skb->h.th; + + th->seq = htonl(seq); + th->cwr = 0; + } while (skb->next); + + delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len); + th->check = ~csum_fold(th->check + delta); + if (skb->ip_summed != CHECKSUM_HW) + th->check = csum_fold(csum_partial(skb->h.raw, thlen, + skb->csum)); + +out: + return segs; +} + extern void __skb_cb_too_small_for_tcp(int, int); extern struct tcp_congestion_ops tcp_reno; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 662bd247b..0eadd3a27 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1072,7 +1072,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ else pkt_len = (end_seq - TCP_SKB_CB(skb)->seq); - if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size)) + if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size)) break; pcount = tcp_skb_pcount(skb); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 075216a98..0334bbe10 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -496,6 +496,24 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) } } +int tcp_v4_gso_send_check(struct sk_buff *skb) +{ + struct iphdr *iph; + struct tcphdr *th; + + if (!pskb_may_pull(skb, sizeof(*th))) + return -EINVAL; + + iph = skb->nh.iph; + th = skb->h.th; + + th->check = 0; + th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); + skb->csum = offsetof(struct tcphdr, check); + skb->ip_summed = CHECKSUM_HW; + return 0; +} + /* * This routine will send an RST to the other tcp. * diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 1e848adbc..ba50b52f8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -197,6 +197,7 @@ void tcp_select_initial_window(int __space, __u32 mss, * See RFC1323 for an explanation of the limit to 14 */ space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); + space = min_t(u32, space, *window_clamp); while (space > 65535 && (*rcv_wscale) < 14) { space >>= 1; (*rcv_wscale)++; @@ -511,15 +512,17 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned /* Avoid the costly divide in the normal * non-TSO case. */ - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; } else { unsigned int factor; factor = skb->len + (mss_now - 1); factor /= mss_now; - skb_shinfo(skb)->tso_segs = factor; - skb_shinfo(skb)->tso_size = mss_now; + skb_shinfo(skb)->gso_segs = factor; + skb_shinfo(skb)->gso_size = mss_now; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; } } @@ -912,7 +915,7 @@ static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int if (!tso_segs || (tso_segs > 1 && - skb_shinfo(skb)->tso_size != mss_now)) { + tcp_skb_mss(skb) != mss_now)) { tcp_set_skb_tso_segs(sk, skb, mss_now); tso_segs = tcp_skb_pcount(skb); } @@ -1723,8 +1726,9 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) { if (!pskb_trim(skb, 0)) { TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; skb->ip_summed = CHECKSUM_NONE; skb->csum = 0; } @@ -1929,8 +1933,9 @@ void tcp_send_fin(struct sock *sk) skb->csum = 0; TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN); TCP_SKB_CB(skb)->sacked = 0; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ TCP_SKB_CB(skb)->seq = tp->write_seq; @@ -1962,8 +1967,9 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) skb->csum = 0; TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST); TCP_SKB_CB(skb)->sacked = 0; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; /* Send it off. */ TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp); @@ -2046,8 +2052,9 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn; TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1; TCP_SKB_CB(skb)->sacked = 0; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; th->seq = htonl(TCP_SKB_CB(skb)->seq); th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */ @@ -2151,8 +2158,9 @@ int tcp_connect(struct sock *sk) TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN; TCP_ECN_send_syn(sk, tp, buff); TCP_SKB_CB(buff)->sacked = 0; - skb_shinfo(buff)->tso_segs = 1; - skb_shinfo(buff)->tso_size = 0; + skb_shinfo(buff)->gso_segs = 1; + skb_shinfo(buff)->gso_size = 0; + skb_shinfo(buff)->gso_type = 0; buff->csum = 0; TCP_SKB_CB(buff)->seq = tp->write_seq++; TCP_SKB_CB(buff)->end_seq = tp->write_seq; @@ -2256,8 +2264,9 @@ void tcp_send_ack(struct sock *sk) buff->csum = 0; TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK; TCP_SKB_CB(buff)->sacked = 0; - skb_shinfo(buff)->tso_segs = 1; - skb_shinfo(buff)->tso_size = 0; + skb_shinfo(buff)->gso_segs = 1; + skb_shinfo(buff)->gso_size = 0; + skb_shinfo(buff)->gso_type = 0; /* Send it off, this clears delayed acks for us. */ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp); @@ -2292,8 +2301,9 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent) skb->csum = 0; TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK; TCP_SKB_CB(skb)->sacked = urgent; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; /* Use a previous sequence. This should cause the other * end to send an ack. Don't queue or clone SKB, just diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 4ef8efaf6..ecc4119df 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include #include #include @@ -17,6 +19,8 @@ #include #include +extern int skb_checksum_setup(struct sk_buff *skb); + /* Add encapsulation header. * * In transport mode, the IP header will be moved forward to make space @@ -103,6 +107,10 @@ static int xfrm4_output_one(struct sk_buff *skb) struct xfrm_state *x = dst->xfrm; int err; + err = skb_checksum_setup(skb); + if (err) + goto error_nolock; + if (skb->ip_summed == CHECKSUM_HW) { err = skb_checksum_help(skb, 0); if (err) @@ -152,16 +160,10 @@ error_nolock: goto out_exit; } -static int xfrm4_output_finish(struct sk_buff *skb) +static int xfrm4_output_finish2(struct sk_buff *skb) { int err; -#ifdef CONFIG_NETFILTER - if (!skb->dst->xfrm) { - IPCB(skb)->flags |= IPSKB_REROUTED; - return dst_output(skb); - } -#endif while (likely((err = xfrm4_output_one(skb)) == 0)) { nf_reset(skb); @@ -174,7 +176,7 @@ static int xfrm4_output_finish(struct sk_buff *skb) return dst_output(skb); err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL, - skb->dst->dev, xfrm4_output_finish); + skb->dst->dev, xfrm4_output_finish2); if (unlikely(err != 1)) break; } @@ -182,6 +184,48 @@ static int xfrm4_output_finish(struct sk_buff *skb) return err; } +static int xfrm4_output_finish(struct sk_buff *skb) +{ + struct sk_buff *segs; + +#ifdef CONFIG_NETFILTER + if (!skb->dst->xfrm) { + IPCB(skb)->flags |= IPSKB_REROUTED; + return dst_output(skb); + } +#endif + + if (!skb_is_gso(skb)) + return xfrm4_output_finish2(skb); + + skb->protocol = htons(ETH_P_IP); + segs = skb_gso_segment(skb, 0); + kfree_skb(skb); + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = xfrm4_output_finish2(segs); + + if (unlikely(err)) { + while ((segs = nskb)) { + nskb = segs->next; + segs->next = NULL; + kfree_skb(segs); + } + return err; + } + + segs = nskb; + } while (segs); + + return 0; +} + int xfrm4_output(struct sk_buff *skb) { return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1f5e0c63a..386ca5c41 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2470,6 +2470,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) spin_lock_bh(&ifp->lock); if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || + !(dev->flags&IFF_MULTICAST) || !(ifp->flags&IFA_F_TENTATIVE)) { ifp->flags &= ~IFA_F_TENTATIVE; spin_unlock_bh(&ifp->lock); @@ -2554,6 +2555,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) if (ifp->idev->cnf.forwarding == 0 && ifp->idev->cnf.rtr_solicits > 0 && (dev->flags&IFF_LOOPBACK) == 0 && + (dev->flags & IFF_MULTICAST) && (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { struct in6_addr all_routers; diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index a18d42563..9ca783dcc 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -635,14 +635,17 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, struct ipv6_txoptions *opt2; int err; - if (newtype != IPV6_HOPOPTS && opt->hopopt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); - if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); - if (newtype != IPV6_RTHDR && opt->srcrt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); - if (newtype != IPV6_DSTOPTS && opt->dst1opt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); + if (opt) { + if (newtype != IPV6_HOPOPTS && opt->hopopt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); + if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); + if (newtype != IPV6_RTHDR && opt->srcrt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); + if (newtype != IPV6_DSTOPTS && opt->dst1opt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); + } + if (newopt && newoptlen) tot_len += CMSG_ALIGN(newoptlen); @@ -659,25 +662,25 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, opt2->tot_len = tot_len; p = (char *)(opt2 + 1); - err = ipv6_renew_option(opt->hopopt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen, newtype != IPV6_HOPOPTS, &opt2->hopopt, &p); if (err) goto out; - err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen, newtype != IPV6_RTHDRDSTOPTS, &opt2->dst0opt, &p); if (err) goto out; - err = ipv6_renew_option(opt->srcrt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen, newtype != IPV6_RTHDR, - (struct ipv6_opt_hdr **)opt2->srcrt, &p); + (struct ipv6_opt_hdr **)&opt2->srcrt, &p); if (err) goto out; - err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen, newtype != IPV6_DSTOPTS, &opt2->dst1opt, &p); if (err) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e46048974..1d5dfeb26 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *skb) int ip6_output(struct sk_buff *skb) { - if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) || + if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) || dst_allfrag(skb->dst)) return ip6_fragment(skb, ip6_output2); else @@ -830,8 +830,9 @@ static inline int ip6_ufo_append_data(struct sock *sk, struct frag_hdr fhdr; /* specify the length of each IP datagram fragment*/ - skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - - sizeof(struct frag_hdr); + skb_shinfo(skb)->gso_size = mtu - fragheaderlen - + sizeof(struct frag_hdr); + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; ipv6_select_ident(skb, &fhdr); skb_shinfo(skb)->ip6_frag_id = fhdr.identification; __skb_queue_tail(&sk->sk_write_queue, skb); @@ -1047,7 +1048,7 @@ alloc_new_skb: skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; - skb_trim(skb_prev, maxfraglen); + pskb_trim_unique(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; if (copy < 0) { diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 486364360..96cac9a94 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -65,7 +65,7 @@ static LIST_HEAD(ipcomp6_tfms_list); static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) { - int err = 0; + int err = -ENOMEM; u8 nexthdr = 0; int hdr_len = skb->h.raw - skb->nh.raw; unsigned char *tmp_hdr = NULL; @@ -76,11 +76,8 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) struct crypto_tfm *tfm; int cpu; - if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) { - err = -ENOMEM; + if (skb_linearize_cow(skb)) goto out; - } skb->ip_summed = CHECKSUM_NONE; @@ -159,10 +156,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) goto out_ok; } - if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) { + if (skb_linearize_cow(skb)) goto out_ok; - } /* compression */ plen = skb->len - hdr_len; diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 80242172a..e9ea33892 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -151,7 +151,7 @@ error_nolock: goto out_exit; } -static int xfrm6_output_finish(struct sk_buff *skb) +static int xfrm6_output_finish2(struct sk_buff *skb) { int err; @@ -167,7 +167,7 @@ static int xfrm6_output_finish(struct sk_buff *skb) return dst_output(skb); err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, - skb->dst->dev, xfrm6_output_finish); + skb->dst->dev, xfrm6_output_finish2); if (unlikely(err != 1)) break; } @@ -175,6 +175,41 @@ static int xfrm6_output_finish(struct sk_buff *skb) return err; } +static int xfrm6_output_finish(struct sk_buff *skb) +{ + struct sk_buff *segs; + + if (!skb_is_gso(skb)) + return xfrm6_output_finish2(skb); + + skb->protocol = htons(ETH_P_IP); + segs = skb_gso_segment(skb, 0); + kfree_skb(skb); + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = xfrm6_output_finish2(segs); + + if (unlikely(err)) { + while ((segs = nskb)) { + nskb = segs->next; + segs->next = NULL; + kfree_skb(segs); + } + return err; + } + + segs = nskb; + } while (segs); + + return 0; +} + int xfrm6_output(struct sk_buff *skb) { return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 811d99872..e6a50e826 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1647,7 +1647,8 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty ipx_pktsize = ntohs(ipx->ipx_pktsize); /* Too small or invalid header? */ - if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len) + if (ipx_pktsize < sizeof(struct ipxhdr) + || !pskb_may_pull(skb, ipx_pktsize)) goto drop; if (ipx->ipx_checksum != IPX_NO_CHECKSUM && diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 61cdda4e5..b59d3b2bd 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -366,6 +366,9 @@ __nfulnl_send(struct nfulnl_instance *inst) if (timer_pending(&inst->timer)) del_timer(&inst->timer); + if (!inst->skb) + return 0; + if (inst->qlen > 1) inst->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 2ffa11c6e..eb7dc2947 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -251,15 +251,17 @@ tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref) RTA_PUT(skb, a->order, 0, NULL); err = tcf_action_dump_1(skb, a, bind, ref); if (err < 0) - goto rtattr_failure; + goto errout; r->rta_len = skb->tail - (u8*)r; } return 0; rtattr_failure: + err = -EINVAL; +errout: skb_trim(skb, b - skb->data); - return -err; + return err; } struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, @@ -306,6 +308,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, goto err_mod; } #endif + *err = -ENOENT; goto err_out; } @@ -777,7 +780,7 @@ replay: return ret; } -static char * +static struct rtattr * find_dump_kind(struct nlmsghdr *n) { struct rtattr *tb1, *tb2[TCA_ACT_MAX+1]; @@ -805,7 +808,7 @@ find_dump_kind(struct nlmsghdr *n) return NULL; kind = tb2[TCA_ACT_KIND-1]; - return (char *) RTA_DATA(kind); + return kind; } static int @@ -818,16 +821,15 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) struct tc_action a; int ret = 0; struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh); - char *kind = find_dump_kind(cb->nlh); + struct rtattr *kind = find_dump_kind(cb->nlh); if (kind == NULL) { printk("tc_dump_action: action bad kind\n"); return 0; } - a_o = tc_lookup_action_n(kind); + a_o = tc_lookup_action(kind); if (a_o == NULL) { - printk("failed to find %s\n", kind); return 0; } @@ -835,7 +837,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) a.ops = a_o; if (a_o->walk == NULL) { - printk("tc_dump_action: %s !capable of dumping table\n", kind); + printk("tc_dump_action: %s !capable of dumping table\n", a_o->kind); goto rtattr_failure; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 138ea92ed..74d4a1dce 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -72,9 +72,9 @@ void qdisc_unlock_tree(struct net_device *dev) dev->queue_lock serializes queue accesses for this device AND dev->qdisc pointer itself. - dev->xmit_lock serializes accesses to device driver. + netif_tx_lock serializes accesses to device driver. - dev->queue_lock and dev->xmit_lock are mutually exclusive, + dev->queue_lock and netif_tx_lock are mutually exclusive, if one is grabbed, another must be free. */ @@ -90,14 +90,17 @@ void qdisc_unlock_tree(struct net_device *dev) NOTE: Called under dev->queue_lock with locally disabled BH. */ -int qdisc_restart(struct net_device *dev) +static inline int qdisc_restart(struct net_device *dev) { struct Qdisc *q = dev->qdisc; struct sk_buff *skb; /* Dequeue packet */ - if ((skb = q->dequeue(q)) != NULL) { + if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) { unsigned nolock = (dev->features & NETIF_F_LLTX); + + dev->gso_skb = NULL; + /* * When the driver has LLTX set it does its own locking * in start_xmit. No need to add additional overhead by @@ -108,7 +111,7 @@ int qdisc_restart(struct net_device *dev) * will be requeued. */ if (!nolock) { - if (!spin_trylock(&dev->xmit_lock)) { + if (!netif_tx_trylock(dev)) { collision: /* So, someone grabbed the driver. */ @@ -126,8 +129,6 @@ int qdisc_restart(struct net_device *dev) __get_cpu_var(netdev_rx_stat).cpu_collision++; goto requeue; } - /* Remember that the driver is grabbed by us. */ - dev->xmit_lock_owner = smp_processor_id(); } { @@ -136,14 +137,11 @@ int qdisc_restart(struct net_device *dev) if (!netif_queue_stopped(dev)) { int ret; - if (netdev_nit) - dev_queue_xmit_nit(skb, dev); - ret = dev->hard_start_xmit(skb, dev); + ret = dev_hard_start_xmit(skb, dev); if (ret == NETDEV_TX_OK) { if (!nolock) { - dev->xmit_lock_owner = -1; - spin_unlock(&dev->xmit_lock); + netif_tx_unlock(dev); } spin_lock(&dev->queue_lock); return -1; @@ -157,8 +155,7 @@ int qdisc_restart(struct net_device *dev) /* NETDEV_TX_BUSY - we need to requeue */ /* Release the driver */ if (!nolock) { - dev->xmit_lock_owner = -1; - spin_unlock(&dev->xmit_lock); + netif_tx_unlock(dev); } spin_lock(&dev->queue_lock); q = dev->qdisc; @@ -175,7 +172,10 @@ int qdisc_restart(struct net_device *dev) */ requeue: - q->ops->requeue(skb, q); + if (skb->next) + dev->gso_skb = skb; + else + q->ops->requeue(skb, q); netif_schedule(dev); return 1; } @@ -183,11 +183,23 @@ requeue: return q->q.qlen; } +void __qdisc_run(struct net_device *dev) +{ + if (unlikely(dev->qdisc == &noop_qdisc)) + goto out; + + while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) + /* NOTHING */; + +out: + clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); +} + static void dev_watchdog(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; - spin_lock(&dev->xmit_lock); + netif_tx_lock(dev); if (dev->qdisc != &noop_qdisc) { if (netif_device_present(dev) && netif_running(dev) && @@ -203,7 +215,7 @@ static void dev_watchdog(unsigned long arg) dev_hold(dev); } } - spin_unlock(&dev->xmit_lock); + netif_tx_unlock(dev); dev_put(dev); } @@ -227,17 +239,17 @@ void __netdev_watchdog_up(struct net_device *dev) static void dev_watchdog_up(struct net_device *dev) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); __netdev_watchdog_up(dev); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } static void dev_watchdog_down(struct net_device *dev) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); if (del_timer(&dev->watchdog_timer)) dev_put(dev); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } void netif_carrier_on(struct net_device *dev) @@ -579,10 +591,17 @@ void dev_deactivate(struct net_device *dev) dev_watchdog_down(dev); - while (test_bit(__LINK_STATE_SCHED, &dev->state)) + /* Wait for outstanding dev_queue_xmit calls. */ + synchronize_rcu(); + + /* Wait for outstanding qdisc_run calls. */ + while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) yield(); - spin_unlock_wait(&dev->xmit_lock); + if (dev->gso_skb) { + kfree_skb(dev->gso_skb); + dev->gso_skb = NULL; + } } void dev_init_scheduler(struct net_device *dev) @@ -624,6 +643,5 @@ EXPORT_SYMBOL(qdisc_create_dflt); EXPORT_SYMBOL(qdisc_alloc); EXPORT_SYMBOL(qdisc_destroy); EXPORT_SYMBOL(qdisc_reset); -EXPORT_SYMBOL(qdisc_restart); EXPORT_SYMBOL(qdisc_lock_tree); EXPORT_SYMBOL(qdisc_unlock_tree); diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 79b8ef34c..4c16ad57a 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -302,20 +302,17 @@ restart: switch (teql_resolve(skb, skb_res, slave)) { case 0: - if (spin_trylock(&slave->xmit_lock)) { - slave->xmit_lock_owner = smp_processor_id(); + if (netif_tx_trylock(slave)) { if (!netif_queue_stopped(slave) && slave->hard_start_xmit(skb, slave) == 0) { - slave->xmit_lock_owner = -1; - spin_unlock(&slave->xmit_lock); + netif_tx_unlock(slave); master->slaves = NEXT_SLAVE(q); netif_wake_queue(dev); master->stats.tx_packets++; master->stats.tx_bytes += len; return 0; } - slave->xmit_lock_owner = -1; - spin_unlock(&slave->xmit_lock); + netif_tx_unlock(slave); } if (netif_queue_stopped(dev)) busy = 1; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 5e0de3c0e..b9b907023 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -806,38 +806,26 @@ no_mem: /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, - const struct sctp_chunk *chunk, - const struct msghdr *msg) + const struct msghdr *msg, + size_t paylen) { struct sctp_chunk *retval; - void *payload = NULL, *payoff; - size_t paylen = 0; - struct iovec *iov = NULL; - int iovlen = 0; - - if (msg) { - iov = msg->msg_iov; - iovlen = msg->msg_iovlen; - paylen = get_user_iov_size(iov, iovlen); - } + void *payload = NULL; + int err; - retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen); + retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen); if (!retval) goto err_chunk; if (paylen) { /* Put the msg_iov together into payload. */ - payload = kmalloc(paylen, GFP_ATOMIC); + payload = kmalloc(paylen, GFP_KERNEL); if (!payload) goto err_payload; - payoff = payload; - for (; iovlen > 0; --iovlen) { - if (copy_from_user(payoff, iov->iov_base,iov->iov_len)) - goto err_copy; - payoff += iov->iov_len; - iov++; - } + err = memcpy_fromiovec(payload, msg->msg_iov, paylen); + if (err < 0) + goto err_copy; } sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 9e58144f4..66e9c5b27 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4026,18 +4026,12 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( * from its upper layer, but retransmits data to the far end * if necessary to fill gaps. */ - struct msghdr *msg = arg; - struct sctp_chunk *abort; + struct sctp_chunk *abort = arg; sctp_disposition_t retval; retval = SCTP_DISPOSITION_CONSUME; - /* Generate ABORT chunk to send the peer. */ - abort = sctp_make_abort_user(asoc, NULL, msg); - if (!abort) - retval = SCTP_DISPOSITION_NOMEM; - else - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); /* Even if we can't send the ABORT due to low memory delete the * TCB. This is a departure from our typical NOMEM handling. @@ -4161,8 +4155,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( void *arg, sctp_cmd_seq_t *commands) { - struct msghdr *msg = arg; - struct sctp_chunk *abort; + struct sctp_chunk *abort = arg; sctp_disposition_t retval; /* Stop T1-init timer */ @@ -4170,12 +4163,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); retval = SCTP_DISPOSITION_CONSUME; - /* Generate ABORT chunk to send the peer */ - abort = sctp_make_abort_user(asoc, NULL, msg); - if (!abort) - retval = SCTP_DISPOSITION_NOMEM; - else - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_CLOSED)); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b811691c3..5b1c8375c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1246,9 +1246,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) } } - if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) - sctp_primitive_ABORT(asoc, NULL); - else + if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { + struct sctp_chunk *chunk; + + chunk = sctp_make_abort_user(asoc, NULL, 0); + if (chunk) + sctp_primitive_ABORT(asoc, chunk); + } else sctp_primitive_SHUTDOWN(asoc, NULL); } @@ -1477,8 +1481,16 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; } if (sinfo_flags & SCTP_ABORT) { + struct sctp_chunk *chunk; + + chunk = sctp_make_abort_user(asoc, msg, msg_len); + if (!chunk) { + err = -ENOMEM; + goto out_unlock; + } + SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); - sctp_primitive_ABORT(asoc, msg); + sctp_primitive_ABORT(asoc, chunk); err = 0; goto out_unlock; } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 7026b0866..00cb388ec 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -71,7 +71,12 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, new = detail->alloc(); if (!new) return NULL; + /* must fully initialise 'new', else + * we might get lose if we need to + * cache_put it soon. + */ cache_init(new); + detail->init(new, key); write_lock(&detail->hash_lock); @@ -85,7 +90,6 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, return tmp; } } - detail->init(new, key); new->next = *head; *head = new; detail->entries++; diff --git a/scripts/basic/.docproc.cmd b/scripts/basic/.docproc.cmd index e725e6b22..c9e1b962d 100644 --- a/scripts/basic/.docproc.cmd +++ b/scripts/basic/.docproc.cmd @@ -1,4 +1,4 @@ -cmd_scripts/basic/docproc := gcc -Wp,-MD,scripts/basic/.docproc.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/docproc scripts/basic/docproc.c +cmd_scripts/basic/docproc := gcc -Wp,-MD,scripts/basic/.docproc.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/docproc scripts/basic/docproc.c deps_scripts/basic/docproc := \ scripts/basic/docproc.c \ @@ -6,16 +6,17 @@ deps_scripts/basic/docproc := \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stddef.h \ - /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ + /usr/include/gnu/stubs-32.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ + /usr/include/bits/types.h \ /usr/include/bits/typesizes.h \ /usr/include/libio.h \ /usr/include/_G_config.h \ /usr/include/wchar.h \ /usr/include/bits/wchar.h \ /usr/include/gconv.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdarg.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ /usr/include/bits/stdio.h \ @@ -30,7 +31,6 @@ deps_scripts/basic/docproc := \ /usr/include/bits/time.h \ /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/alloca.h \ /usr/include/string.h \ /usr/include/bits/string.h \ @@ -40,8 +40,8 @@ deps_scripts/basic/docproc := \ /usr/include/bits/posix_opt.h \ /usr/include/bits/confname.h \ /usr/include/getopt.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/limits.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/syslimits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/limits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/syslimits.h \ /usr/include/limits.h \ /usr/include/bits/posix1_lim.h \ /usr/include/bits/local_lim.h \ @@ -54,9 +54,6 @@ deps_scripts/basic/docproc := \ /usr/include/bits/sigaction.h \ /usr/include/bits/sigcontext.h \ /usr/include/asm/sigcontext.h \ - /usr/include/linux/compiler.h \ - /usr/include/linux/compiler-gcc3.h \ - /usr/include/linux/compiler-gcc.h \ /usr/include/bits/sigstack.h \ /usr/include/bits/sigthread.h \ /usr/include/sys/resource.h \ diff --git a/scripts/basic/.fixdep.cmd b/scripts/basic/.fixdep.cmd index 1c463aa74..fc3d06a8d 100644 --- a/scripts/basic/.fixdep.cmd +++ b/scripts/basic/.fixdep.cmd @@ -1,4 +1,4 @@ -cmd_scripts/basic/fixdep := gcc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/fixdep scripts/basic/fixdep.c +cmd_scripts/basic/fixdep := gcc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/fixdep scripts/basic/fixdep.c deps_scripts/basic/fixdep := \ scripts/basic/fixdep.c \ @@ -6,13 +6,15 @@ deps_scripts/basic/fixdep := \ $(wildcard include/config/my/option.h) \ $(wildcard include/config/.h) \ $(wildcard include/config/foo.h) \ + $(wildcard include/config/boom.h) \ /usr/include/sys/types.h \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ - /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stddef.h \ + /usr/include/gnu/stubs-32.h \ + /usr/include/bits/types.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ /usr/include/bits/typesizes.h \ /usr/include/time.h \ /usr/include/endian.h \ @@ -23,7 +25,6 @@ deps_scripts/basic/fixdep := \ /usr/include/bits/time.h \ /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/sys/stat.h \ /usr/include/bits/stat.h \ /usr/include/sys/mman.h \ @@ -45,18 +46,19 @@ deps_scripts/basic/fixdep := \ /usr/include/wchar.h \ /usr/include/bits/wchar.h \ /usr/include/gconv.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdarg.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ /usr/include/bits/stdio.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/limits.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/syslimits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/limits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/syslimits.h \ /usr/include/limits.h \ /usr/include/bits/posix1_lim.h \ /usr/include/bits/local_lim.h \ /usr/include/linux/limits.h \ /usr/include/bits/posix2_lim.h \ /usr/include/ctype.h \ + /usr/include/arpa/inet.h \ /usr/include/netinet/in.h \ /usr/include/stdint.h \ /usr/include/sys/socket.h \ diff --git a/scripts/basic/.split-include.cmd b/scripts/basic/.split-include.cmd index e596a8729..b73a7c813 100644 --- a/scripts/basic/.split-include.cmd +++ b/scripts/basic/.split-include.cmd @@ -1,4 +1,4 @@ -cmd_scripts/basic/split-include := gcc -Wp,-MD,scripts/basic/.split-include.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/split-include scripts/basic/split-include.c +cmd_scripts/basic/split-include := gcc -Wp,-MD,scripts/basic/.split-include.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/split-include scripts/basic/split-include.c deps_scripts/basic/split-include := \ scripts/basic/split-include.c \ @@ -7,9 +7,10 @@ deps_scripts/basic/split-include := \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ - /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stddef.h \ + /usr/include/gnu/stubs-32.h \ + /usr/include/bits/types.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ /usr/include/bits/typesizes.h \ /usr/include/time.h \ /usr/include/bits/stat.h \ @@ -22,14 +23,11 @@ deps_scripts/basic/split-include := \ /usr/include/bits/time.h \ /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/ctype.h \ /usr/include/errno.h \ /usr/include/bits/errno.h \ /usr/include/linux/errno.h \ /usr/include/asm/errno.h \ - /usr/include/asm-generic/errno.h \ - /usr/include/asm-generic/errno-base.h \ /usr/include/fcntl.h \ /usr/include/bits/fcntl.h \ /usr/include/stdio.h \ @@ -38,7 +36,7 @@ deps_scripts/basic/split-include := \ /usr/include/wchar.h \ /usr/include/bits/wchar.h \ /usr/include/gconv.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdarg.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ /usr/include/bits/stdio.h \ diff --git a/scripts/basic/docproc b/scripts/basic/docproc index 51640ad93..939288420 100755 Binary files a/scripts/basic/docproc and b/scripts/basic/docproc differ diff --git a/scripts/basic/fixdep b/scripts/basic/fixdep index 800beedb0..942fd7c59 100755 Binary files a/scripts/basic/fixdep and b/scripts/basic/fixdep differ diff --git a/scripts/basic/split-include b/scripts/basic/split-include index ecd686e99..2e76d8ead 100755 Binary files a/scripts/basic/split-include and b/scripts/basic/split-include differ diff --git a/scripts/kconfig/.conf.cmd b/scripts/kconfig/.conf.cmd index 4f007fa36..a09989cdf 100644 --- a/scripts/kconfig/.conf.cmd +++ b/scripts/kconfig/.conf.cmd @@ -1 +1 @@ -cmd_scripts/kconfig/conf := gcc -o scripts/kconfig/conf scripts/kconfig/conf.o -Wl,-rpath,\$$ORIGIN -Lscripts/kconfig -lkconfig +cmd_scripts/kconfig/conf := gcc -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o diff --git a/scripts/kconfig/.conf.o.cmd b/scripts/kconfig/.conf.o.cmd index 2c06e27ab..b04aab77b 100644 --- a/scripts/kconfig/.conf.o.cmd +++ b/scripts/kconfig/.conf.o.cmd @@ -3,13 +3,15 @@ cmd_scripts/kconfig/conf.o := gcc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wstri deps_scripts/kconfig/conf.o := \ scripts/kconfig/conf.c \ $(wildcard include/config/.h) \ + $(wildcard include/config/allconfig.h) \ /usr/include/ctype.h \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ - /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stddef.h \ + /usr/include/gnu/stubs-32.h \ + /usr/include/bits/types.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ /usr/include/bits/typesizes.h \ /usr/include/endian.h \ /usr/include/bits/endian.h \ @@ -22,8 +24,17 @@ deps_scripts/kconfig/conf.o := \ /usr/include/bits/time.h \ /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/alloca.h \ + /usr/include/stdio.h \ + /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/wchar.h \ + /usr/include/bits/wchar.h \ + /usr/include/gconv.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ + /usr/include/bits/stdio_lim.h \ + /usr/include/bits/sys_errlist.h \ + /usr/include/bits/stdio.h \ /usr/include/string.h \ /usr/include/bits/string.h \ /usr/include/bits/string2.h \ @@ -35,17 +46,10 @@ deps_scripts/kconfig/conf.o := \ /usr/include/bits/stat.h \ scripts/kconfig/lkc.h \ scripts/kconfig/expr.h \ - /usr/include/stdio.h \ - /usr/include/libio.h \ - /usr/include/_G_config.h \ - /usr/include/wchar.h \ - /usr/include/bits/wchar.h \ - /usr/include/gconv.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdarg.h \ - /usr/include/bits/stdio_lim.h \ - /usr/include/bits/sys_errlist.h \ - /usr/include/bits/stdio.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdbool.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdbool.h \ + /usr/include/libintl.h \ + /usr/include/locale.h \ + /usr/include/bits/locale.h \ scripts/kconfig/lkc_proto.h \ scripts/kconfig/conf.o: $(deps_scripts/kconfig/conf.o) diff --git a/scripts/kconfig/.kxgettext.o.cmd b/scripts/kconfig/.kxgettext.o.cmd index 1ef4182d0..f05e92904 100644 --- a/scripts/kconfig/.kxgettext.o.cmd +++ b/scripts/kconfig/.kxgettext.o.cmd @@ -6,10 +6,11 @@ deps_scripts/kconfig/kxgettext.o := \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ - /usr/lib/gcc/i386-redhat-linux/3.4.2/include/stddef.h \ + /usr/include/bits/wordsize.h \ + /usr/include/gnu/stubs-32.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ /usr/include/sys/types.h \ /usr/include/bits/types.h \ - /usr/include/bits/wordsize.h \ /usr/include/bits/typesizes.h \ /usr/include/time.h \ /usr/include/endian.h \ @@ -20,7 +21,6 @@ deps_scripts/kconfig/kxgettext.o := \ /usr/include/bits/time.h \ /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/alloca.h \ /usr/include/string.h \ /usr/include/bits/string.h \ @@ -33,11 +33,11 @@ deps_scripts/kconfig/kxgettext.o := \ /usr/include/wchar.h \ /usr/include/bits/wchar.h \ /usr/include/gconv.h \ - /usr/lib/gcc/i386-redhat-linux/3.4.2/include/stdarg.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ /usr/include/bits/stdio.h \ - /usr/lib/gcc/i386-redhat-linux/3.4.2/include/stdbool.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdbool.h \ /usr/include/libintl.h \ /usr/include/locale.h \ /usr/include/bits/locale.h \ diff --git a/scripts/kconfig/.mconf.o.cmd b/scripts/kconfig/.mconf.o.cmd index 6f874bf8c..bdd903011 100644 --- a/scripts/kconfig/.mconf.o.cmd +++ b/scripts/kconfig/.mconf.o.cmd @@ -2,12 +2,14 @@ cmd_scripts/kconfig/mconf.o := gcc -Wp,-MD,scripts/kconfig/.mconf.o.d -Wall -Wst deps_scripts/kconfig/mconf.o := \ scripts/kconfig/mconf.c \ - $(wildcard include/config/.h) \ $(wildcard include/config/mode.h) \ + $(wildcard include/config/.h) \ /usr/include/sys/ioctl.h \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ + /usr/include/bits/wordsize.h \ + /usr/include/gnu/stubs-32.h \ /usr/include/bits/ioctls.h \ /usr/include/asm/ioctls.h \ /usr/include/asm/ioctl.h \ @@ -17,8 +19,7 @@ deps_scripts/kconfig/mconf.o := \ /usr/include/signal.h \ /usr/include/bits/sigset.h \ /usr/include/bits/types.h \ - /usr/include/bits/wordsize.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stddef.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ /usr/include/bits/typesizes.h \ /usr/include/bits/signum.h \ /usr/include/time.h \ @@ -26,12 +27,8 @@ deps_scripts/kconfig/mconf.o := \ /usr/include/bits/sigaction.h \ /usr/include/bits/sigcontext.h \ /usr/include/asm/sigcontext.h \ - /usr/include/linux/compiler.h \ - /usr/include/linux/compiler-gcc3.h \ - /usr/include/linux/compiler-gcc.h \ /usr/include/bits/sigstack.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/bits/sigthread.h \ /usr/include/sys/resource.h \ /usr/include/bits/resource.h \ @@ -45,22 +42,20 @@ deps_scripts/kconfig/mconf.o := \ /usr/include/bits/errno.h \ /usr/include/linux/errno.h \ /usr/include/asm/errno.h \ - /usr/include/asm-generic/errno.h \ - /usr/include/asm-generic/errno-base.h \ /usr/include/fcntl.h \ /usr/include/bits/fcntl.h \ /usr/include/sys/types.h \ /usr/include/sys/select.h \ /usr/include/bits/select.h \ /usr/include/sys/sysmacros.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/limits.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/syslimits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/limits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/syslimits.h \ /usr/include/limits.h \ /usr/include/bits/posix1_lim.h \ /usr/include/bits/local_lim.h \ /usr/include/linux/limits.h \ /usr/include/bits/posix2_lim.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdarg.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ /usr/include/stdlib.h \ /usr/include/alloca.h \ /usr/include/string.h \ @@ -72,6 +67,8 @@ deps_scripts/kconfig/mconf.o := \ /usr/include/bits/posix_opt.h \ /usr/include/bits/confname.h \ /usr/include/getopt.h \ + /usr/include/locale.h \ + /usr/include/bits/locale.h \ scripts/kconfig/lkc.h \ scripts/kconfig/expr.h \ /usr/include/stdio.h \ @@ -83,7 +80,8 @@ deps_scripts/kconfig/mconf.o := \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ /usr/include/bits/stdio.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdbool.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdbool.h \ + /usr/include/libintl.h \ scripts/kconfig/lkc_proto.h \ scripts/kconfig/mconf.o: $(deps_scripts/kconfig/mconf.o) diff --git a/scripts/kconfig/.zconf.tab.o.cmd b/scripts/kconfig/.zconf.tab.o.cmd index 2a3661c06..b2e450deb 100644 --- a/scripts/kconfig/.zconf.tab.o.cmd +++ b/scripts/kconfig/.zconf.tab.o.cmd @@ -1,4 +1,4 @@ -cmd_scripts/kconfig/zconf.tab.o := gcc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Iscripts/kconfig -fPIC -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c +cmd_scripts/kconfig/zconf.tab.o := gcc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c deps_scripts/kconfig/zconf.tab.o := \ scripts/kconfig/zconf.tab.c \ @@ -6,13 +6,14 @@ deps_scripts/kconfig/zconf.tab.o := \ /usr/include/features.h \ /usr/include/sys/cdefs.h \ /usr/include/gnu/stubs.h \ - /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stddef.h \ + /usr/include/gnu/stubs-32.h \ + /usr/include/bits/types.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stddef.h \ /usr/include/bits/typesizes.h \ /usr/include/endian.h \ /usr/include/bits/endian.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdarg.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdarg.h \ /usr/include/stdio.h \ /usr/include/libio.h \ /usr/include/_G_config.h \ @@ -31,24 +32,25 @@ deps_scripts/kconfig/zconf.tab.o := \ /usr/include/bits/time.h \ /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h \ /usr/include/alloca.h \ /usr/include/string.h \ /usr/include/bits/string.h \ /usr/include/bits/string2.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/stdbool.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/stdbool.h \ scripts/kconfig/lkc.h \ scripts/kconfig/expr.h \ + /usr/include/libintl.h \ + /usr/include/locale.h \ + /usr/include/bits/locale.h \ scripts/kconfig/lkc_proto.h \ + scripts/kconfig/zconf.hash.c \ scripts/kconfig/lex.zconf.c \ /usr/include/errno.h \ /usr/include/bits/errno.h \ /usr/include/linux/errno.h \ /usr/include/asm/errno.h \ - /usr/include/asm-generic/errno.h \ - /usr/include/asm-generic/errno-base.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/limits.h \ - /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.2/include/syslimits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/limits.h \ + /usr/lib/gcc/i386-redhat-linux/4.0.1/include/syslimits.h \ /usr/include/limits.h \ /usr/include/bits/posix1_lim.h \ /usr/include/bits/local_lim.h \ @@ -58,15 +60,24 @@ deps_scripts/kconfig/zconf.tab.o := \ /usr/include/bits/posix_opt.h \ /usr/include/bits/confname.h \ /usr/include/getopt.h \ + scripts/kconfig/lkc.h \ + scripts/kconfig/util.c \ + scripts/kconfig/lkc.h \ scripts/kconfig/confdata.c \ $(wildcard include/config/.h) \ + $(wildcard include/config/notimestamp.h) \ /usr/include/sys/stat.h \ /usr/include/bits/stat.h \ + scripts/kconfig/lkc.h \ scripts/kconfig/expr.c \ + scripts/kconfig/lkc.h \ scripts/kconfig/symbol.c \ + /usr/include/regex.h \ /usr/include/sys/utsname.h \ /usr/include/bits/utsname.h \ + scripts/kconfig/lkc.h \ scripts/kconfig/menu.c \ + scripts/kconfig/lkc.h \ scripts/kconfig/zconf.tab.o: $(deps_scripts/kconfig/zconf.tab.o) diff --git a/scripts/kconfig/conf b/scripts/kconfig/conf index 89b852e2f..3066bc9eb 100755 Binary files a/scripts/kconfig/conf and b/scripts/kconfig/conf differ diff --git a/scripts/kconfig/conf.o b/scripts/kconfig/conf.o index c191a8a72..fc7911451 100644 Binary files a/scripts/kconfig/conf.o and b/scripts/kconfig/conf.o differ diff --git a/scripts/kconfig/kxgettext.o b/scripts/kconfig/kxgettext.o index e92d2605c..531fd7204 100644 Binary files a/scripts/kconfig/kxgettext.o and b/scripts/kconfig/kxgettext.o differ diff --git a/scripts/kconfig/lex.zconf.c b/scripts/kconfig/lex.zconf.c index 22dda11f7..24e3c8cbb 100644 --- a/scripts/kconfig/lex.zconf.c +++ b/scripts/kconfig/lex.zconf.c @@ -1,5 +1,5 @@ -#line 3 "lex.zconf.c" +#line 3 "scripts/kconfig/lex.zconf.c" #define YY_INT_ALIGNED short int @@ -323,7 +323,7 @@ void zconffree (void * ); /* Begin user sect3 */ -#define zconfwrap(n) 1 +#define zconfwrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -338,1567 +338,323 @@ int zconflineno = 1; extern char *zconftext; #define yytext_ptr zconftext -static yyconst flex_int16_t yy_nxt[][38] = +static yyconst flex_int16_t yy_nxt[][17] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }, - - { - 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12 - }, - - { - 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12 - }, - - { - 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 16, 16, 18, 18, 19, 20, - 21, 22, 18, 18, 23, 24, 18, 25, 18, 26, - 27, 18, 28, 29, 30, 18, 18, 16 - }, - - { - 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 16, 16, 18, 18, 19, 20, - 21, 22, 18, 18, 23, 24, 18, 25, 18, 26, - 27, 18, 28, 29, 30, 18, 18, 16 - - }, - - { - 11, 31, 32, 33, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31 - }, - - { - 11, 31, 32, 33, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31 - }, - - { - 11, 34, 34, 35, 34, 36, 34, 34, 36, 34, - 34, 34, 34, 34, 34, 37, 34, 34, 34, 34, - - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34 - }, - - { - 11, 34, 34, 35, 34, 36, 34, 34, 36, 34, - 34, 34, 34, 34, 34, 37, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34 - }, - - { - 11, 38, 38, 39, 40, 41, 42, 43, 41, 44, - 45, 46, 47, 47, 48, 49, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 50, 47, 47, 47, 51, - 47, 47, 47, 47, 47, 47, 47, 52 - - }, - - { - 11, 38, 38, 39, 40, 41, 42, 43, 41, 44, - 45, 46, 47, 47, 48, 49, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 50, 47, 47, 47, 51, - 47, 47, 47, 47, 47, 47, 47, 52 - }, - - { - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11, -11 - }, - - { - 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, - -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, - - -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, - -12, -12, -12, -12, -12, -12, -12, -12 - }, - - { - 11, -13, 53, 54, -13, -13, 55, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13, -13 - }, - - { - 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14, -14 - - }, - - { - 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56 - }, - - { - 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16 - }, - - { - 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, - -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, - - -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, - -17, -17, -17, -17, -17, -17, -17, -17 - }, - - { - 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, - -18, -18, -18, 58, -18, -18, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -18 - }, - - { - 11, -19, -19, -19, -19, -19, -19, -19, -19, -19, - -19, -19, -19, 58, -19, -19, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, - 58, 58, 58, 58, 58, 58, 58, -19 - - }, - - { - 11, -20, -20, -20, -20, -20, -20, -20, -20, -20, - -20, -20, -20, 58, -20, -20, 58, 58, 58, 58, - 58, 58, 58, 58, 60, 58, 58, 58, 58, 61, - 58, 58, 58, 58, 58, 58, 58, -20 - }, - - { - 11, -21, -21, -21, -21, -21, -21, -21, -21, -21, - -21, -21, -21, 58, -21, -21, 58, 58, 58, 58, - 58, 62, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -21 - }, - - { - 11, -22, -22, -22, -22, -22, -22, -22, -22, -22, - -22, -22, -22, 58, -22, -22, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 63, 58, - 58, 58, 58, 58, 58, 58, 58, -22 - }, - - { - 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, - -23, -23, -23, 58, -23, -23, 58, 58, 58, 58, - 58, 64, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -23 - }, - - { - 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, - -24, -24, -24, 58, -24, -24, 58, 58, 58, 58, - 58, 58, 65, 58, 58, 58, 58, 58, 66, 58, - 58, 58, 58, 58, 58, 58, 58, -24 - - }, - - { - 11, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, 58, -25, -25, 58, 67, 58, 58, - 58, 68, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -25 - }, - - { - 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, - -26, -26, -26, 58, -26, -26, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 69, 58, 58, 58, 58, 58, 58, -26 - }, - - { - 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, - -27, -27, -27, 58, -27, -27, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 70, 58, 58, 58, 58, -27 - }, - - { - 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, - -28, -28, -28, 58, -28, -28, 58, 71, 58, 58, - 58, 72, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -28 - }, - - { - 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, 58, -29, -29, 58, 58, 58, 58, - 58, 73, 58, 58, 58, 58, 58, 58, 58, 74, - 58, 58, 58, 58, 75, 58, 58, -29 - - }, - - { - 11, -30, -30, -30, -30, -30, -30, -30, -30, -30, - -30, -30, -30, 58, -30, -30, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 76, 58, 58, 58, 58, -30 - }, - - { - 11, 77, 77, -31, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77 - }, - - { - 11, -32, 78, 79, -32, -32, -32, -32, -32, -32, - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, - - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, - -32, -32, -32, -32, -32, -32, -32, -32 - }, - - { - 11, 80, -33, -33, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80 - }, - - { - 11, 81, 81, 82, 81, -34, 81, 81, -34, 81, - 81, 81, 81, 81, 81, -34, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81 - - }, - - { - 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, -35, -35, -35, -35, -35 - }, - - { - 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36, -36 - }, - - { - 11, 83, 83, 84, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83 - }, - - { - 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, -38, -38 - }, - - { - 11, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39 - - }, - - { - 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, - -40, -40, -40, -40, 85, -40, -40, -40, -40, -40, - -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, - -40, -40, -40, -40, -40, -40, -40, -40 - }, - - { - 11, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, -41, -41, -41, -41, -41 - }, - - { - 11, 86, 86, -42, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86 - }, - - { - 11, -43, -43, -43, -43, -43, -43, 87, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43 - }, - - { - 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, -44, -44, -44, -44, -44 - - }, - - { - 11, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, -45 - }, - - { - 11, -46, -46, -46, -46, -46, -46, -46, -46, -46, - -46, 88, 89, 89, -46, -46, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -46 - }, - - { - 11, -47, -47, -47, -47, -47, -47, -47, -47, -47, - -47, 89, 89, 89, -47, -47, 89, 89, 89, 89, - - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -47 - }, - - { - 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, -48 - }, - - { - 11, -49, -49, 90, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49 - - }, - - { - 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, - -50, 89, 89, 89, -50, -50, 89, 89, 89, 89, - 89, 89, 91, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -50 - }, - - { - 11, -51, -51, -51, -51, -51, -51, -51, -51, -51, - -51, 89, 89, 89, -51, -51, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 92, 89, - 89, 89, 89, 89, 89, 89, 89, -51 - }, - - { - 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, - -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, - - -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, - -52, -52, -52, -52, -52, -52, -52, 93 - }, - - { - 11, -53, 53, 54, -53, -53, 55, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53, -53 - }, - - { - 11, -54, -54, -54, -54, -54, -54, -54, -54, -54, - -54, -54, -54, -54, -54, -54, -54, -54, -54, -54, - -54, -54, -54, -54, -54, -54, -54, -54, -54, -54, - -54, -54, -54, -54, -54, -54, -54, -54 - - }, - - { - 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56 - }, - - { - 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56 - }, - - { - 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, - -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, - - -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, - -57, -57, -57, -57, -57, -57, -57, -57 - }, - - { - 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, - -58, -58, -58, 58, -58, -58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -58 - }, - - { - 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, - -59, -59, -59, 58, -59, -59, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 94, - 58, 58, 58, 58, 58, 58, 58, -59 - - }, - - { - 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, - -60, -60, -60, 58, -60, -60, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 95, - 58, 58, 58, 58, 58, 58, 58, -60 - }, - - { - 11, -61, -61, -61, -61, -61, -61, -61, -61, -61, - -61, -61, -61, 58, -61, -61, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 96, 97, 58, - 58, 58, 58, 58, 58, 58, 58, -61 - }, - - { - 11, -62, -62, -62, -62, -62, -62, -62, -62, -62, - -62, -62, -62, 58, -62, -62, 58, 58, 58, 58, - - 58, 58, 98, 58, 58, 58, 58, 58, 58, 58, - 99, 58, 58, 58, 58, 58, 58, -62 - }, - - { - 11, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -63, -63, 58, -63, -63, 58, 100, 58, 58, - 101, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -63 - }, - - { - 11, -64, -64, -64, -64, -64, -64, -64, -64, -64, - -64, -64, -64, 58, -64, -64, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 102, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 103, -64 - - }, - - { - 11, -65, -65, -65, -65, -65, -65, -65, -65, -65, - -65, -65, -65, 58, -65, -65, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -65 - }, - - { - 11, -66, -66, -66, -66, -66, -66, -66, -66, -66, - -66, -66, -66, 58, -66, -66, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 104, 58, 58, -66 - }, - - { - 11, -67, -67, -67, -67, -67, -67, -67, -67, -67, - -67, -67, -67, 58, -67, -67, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 105, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -67 - }, - - { - 11, -68, -68, -68, -68, -68, -68, -68, -68, -68, - -68, -68, -68, 58, -68, -68, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 106, 58, - 58, 58, 58, 58, 58, 58, 58, -68 - }, - - { - 11, -69, -69, -69, -69, -69, -69, -69, -69, -69, - -69, -69, -69, 58, -69, -69, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 107, 58, 58, -69 - - }, - - { - 11, -70, -70, -70, -70, -70, -70, -70, -70, -70, - -70, -70, -70, 58, -70, -70, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 108, - 58, 58, 58, 58, 58, 58, 58, -70 - }, - - { - 11, -71, -71, -71, -71, -71, -71, -71, -71, -71, - -71, -71, -71, 58, -71, -71, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 109, 58, - 58, 58, 58, 58, 58, 58, 58, -71 - }, - - { - 11, -72, -72, -72, -72, -72, -72, -72, -72, -72, - -72, -72, -72, 58, -72, -72, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 110, 58, 58, 58, 58, 58, -72 - }, - - { - 11, -73, -73, -73, -73, -73, -73, -73, -73, -73, - -73, -73, -73, 58, -73, -73, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 111, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -73 - }, - - { - 11, -74, -74, -74, -74, -74, -74, -74, -74, -74, - -74, -74, -74, 58, -74, -74, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 112, 58, -74 - - }, - - { - 11, -75, -75, -75, -75, -75, -75, -75, -75, -75, - -75, -75, -75, 58, -75, -75, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 113, 58, 58, 58, 58, -75 - }, - - { - 11, -76, -76, -76, -76, -76, -76, -76, -76, -76, - -76, -76, -76, 58, -76, -76, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 114, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -76 - }, - - { - 11, 77, 77, -77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77 - }, - - { - 11, -78, 78, 79, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78 - }, - - { - 11, 80, -79, -79, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80 - - }, - - { - 11, -80, -80, -80, -80, -80, -80, -80, -80, -80, - -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, - -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, - -80, -80, -80, -80, -80, -80, -80, -80 - }, - - { - 11, 81, 81, 82, 81, -81, 81, 81, -81, 81, - 81, 81, 81, 81, 81, -81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81 - }, - - { - 11, -82, -82, -82, -82, -82, -82, -82, -82, -82, - -82, -82, -82, -82, -82, -82, -82, -82, -82, -82, - - -82, -82, -82, -82, -82, -82, -82, -82, -82, -82, - -82, -82, -82, -82, -82, -82, -82, -82 - }, - - { - 11, -83, -83, 84, -83, -83, -83, -83, -83, -83, - -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, - -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, - -83, -83, -83, -83, -83, -83, -83, -83 - }, - - { - 11, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, -84, -84, -84, -84, -84, -84, -84 - - }, - - { - 11, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, -85, -85, -85, -85, -85, -85, -85 - }, - - { - 11, 86, 86, -86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86 - }, - - { - 11, -87, -87, -87, -87, -87, -87, -87, -87, -87, - -87, -87, -87, -87, -87, -87, -87, -87, -87, -87, - - -87, -87, -87, -87, -87, -87, -87, -87, -87, -87, - -87, -87, -87, -87, -87, -87, -87, -87 - }, - - { - 11, -88, -88, -88, -88, -88, -88, -88, -88, -88, - -88, 115, 89, 89, -88, -88, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -88 - }, - - { - 11, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, 89, 89, 89, -89, -89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -89 - - }, - - { - 11, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90 - }, - - { - 11, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, 89, 89, 89, -91, -91, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -91 - }, - - { - 11, -92, -92, -92, -92, -92, -92, -92, -92, -92, - -92, 89, 89, 89, -92, -92, 89, 89, 89, 89, - - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -92 - }, - - { - 11, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, -93, -93, -93, -93, -93 - }, - - { - 11, -94, -94, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, 58, -94, -94, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 116, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -94 - - }, - - { - 11, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, 58, -95, -95, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 117, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -95 - }, - - { - 11, -96, -96, -96, -96, -96, -96, -96, -96, -96, - -96, -96, -96, 58, -96, -96, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 118, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -96 - }, - - { - 11, -97, -97, -97, -97, -97, -97, -97, -97, -97, - -97, -97, -97, 58, -97, -97, 58, 58, 58, 58, - - 58, 58, 119, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -97 - }, - - { - 11, -98, -98, -98, -98, -98, -98, -98, -98, -98, - -98, -98, -98, 58, -98, -98, 120, 121, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -98 - }, - - { - 11, -99, -99, -99, -99, -99, -99, -99, -99, -99, - -99, -99, -99, 58, -99, -99, 58, 58, 58, 58, - 58, 122, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -99 - - }, - - { - 11, -100, -100, -100, -100, -100, -100, -100, -100, -100, - -100, -100, -100, 58, -100, -100, 58, 58, 123, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -100 - }, - - { - 11, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, 58, -101, -101, 58, 58, 58, 124, - 58, 58, 58, 58, 58, 125, 58, 126, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -101 - }, - - { - 11, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, 58, -102, -102, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 127, 58, 58, 58, 58, 58, 58, -102 - }, - - { - 11, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, 58, -103, -103, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -103 - }, - - { - 11, -104, -104, -104, -104, -104, -104, -104, -104, -104, - -104, -104, -104, 58, -104, -104, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -104 - - }, - - { - 11, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, 58, -105, -105, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 128, 58, - 58, 58, 58, 58, 58, 58, 58, -105 - }, - - { - 11, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, 58, -106, -106, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 129, 58, -106 - }, - - { - 11, -107, -107, -107, -107, -107, -107, -107, -107, -107, - -107, -107, -107, 58, -107, -107, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 130, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -107 - }, - - { - 11, -108, -108, -108, -108, -108, -108, -108, -108, -108, - -108, -108, -108, 58, -108, -108, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 131, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -108 - }, - - { - 11, -109, -109, -109, -109, -109, -109, -109, -109, -109, - -109, -109, -109, 58, -109, -109, 58, 58, 58, 58, - 58, 58, 58, 132, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -109 - - }, - - { - 11, -110, -110, -110, -110, -110, -110, -110, -110, -110, - -110, -110, -110, 58, -110, -110, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 133, 58, -110 - }, - - { - 11, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 58, -111, -111, 58, 58, 58, 58, - 58, 134, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -111 - }, - - { - 11, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, 58, -112, -112, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 135, 58, 58, 58, 58, -112 - }, - - { - 11, -113, -113, -113, -113, -113, -113, -113, -113, -113, - -113, -113, -113, 58, -113, -113, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 136, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -113 - }, - - { - 11, -114, -114, -114, -114, -114, -114, -114, -114, -114, - -114, -114, -114, 58, -114, -114, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 137, 58, 58, 58, -114 - - }, - - { - 11, -115, -115, -115, -115, -115, -115, -115, -115, -115, - -115, 89, 89, 89, -115, -115, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -115 - }, - - { - 11, -116, -116, -116, -116, -116, -116, -116, -116, -116, - -116, -116, -116, 58, -116, -116, 58, 58, 58, 58, - 58, 138, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -116 - }, - - { - 11, -117, -117, -117, -117, -117, -117, -117, -117, -117, - -117, -117, -117, 58, -117, -117, 58, 58, 58, 139, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -117 - }, - - { - 11, -118, -118, -118, -118, -118, -118, -118, -118, -118, - -118, -118, -118, 58, -118, -118, 58, 58, 58, 58, - 58, 140, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -118 - }, - - { - 11, -119, -119, -119, -119, -119, -119, -119, -119, -119, - -119, -119, -119, 58, -119, -119, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 141, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -119 - - }, - - { - 11, -120, -120, -120, -120, -120, -120, -120, -120, -120, - -120, -120, -120, 58, -120, -120, 58, 58, 142, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 143, 58, 58, -120 - }, - - { - 11, -121, -121, -121, -121, -121, -121, -121, -121, -121, - -121, -121, -121, 58, -121, -121, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 144, 58, -121 - }, - - { - 11, -122, -122, -122, -122, -122, -122, -122, -122, -122, - -122, -122, -122, 58, -122, -122, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 145, 58, - 58, 58, 58, 58, 58, 58, 58, -122 - }, - - { - 11, -123, -123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, 58, -123, -123, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 146, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -123 - }, - - { - 11, -124, -124, -124, -124, -124, -124, -124, -124, -124, - -124, -124, -124, 58, -124, -124, 58, 58, 58, 58, - 58, 58, 58, 58, 147, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -124 - - }, - - { - 11, -125, -125, -125, -125, -125, -125, -125, -125, -125, - -125, -125, -125, 58, -125, -125, 58, 58, 58, 58, - 58, 58, 148, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -125 - }, - - { - 11, -126, -126, -126, -126, -126, -126, -126, -126, -126, - -126, -126, -126, 58, -126, -126, 58, 58, 58, 58, - 58, 149, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -126 - }, - - { - 11, -127, -127, -127, -127, -127, -127, -127, -127, -127, - -127, -127, -127, 58, -127, -127, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -127 - }, - - { - 11, -128, -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, 58, -128, -128, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 150, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -128 - }, - - { - 11, -129, -129, -129, -129, -129, -129, -129, -129, -129, - -129, -129, -129, 58, -129, -129, 58, 58, 58, 151, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -129 - - }, - - { - 11, -130, -130, -130, -130, -130, -130, -130, -130, -130, - -130, -130, -130, 58, -130, -130, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 152, - 58, 58, 58, 58, 58, 58, 58, -130 - }, - - { - 11, -131, -131, -131, -131, -131, -131, -131, -131, -131, - -131, -131, -131, 58, -131, -131, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 153, 58, 58, 58, 58, 58, 58, -131 - }, - - { - 11, -132, -132, -132, -132, -132, -132, -132, -132, -132, - -132, -132, -132, 58, -132, -132, 58, 58, 58, 58, - - 58, 154, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -132 - }, - - { - 11, -133, -133, -133, -133, -133, -133, -133, -133, -133, - -133, -133, -133, 58, -133, -133, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 155, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -133 - }, - - { - 11, -134, -134, -134, -134, -134, -134, -134, -134, -134, - -134, -134, -134, 58, -134, -134, 58, 58, 58, 156, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -134 - - }, - - { - 11, -135, -135, -135, -135, -135, -135, -135, -135, -135, - -135, -135, -135, 58, -135, -135, 58, 58, 58, 157, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -135 - }, - - { - 11, -136, -136, -136, -136, -136, -136, -136, -136, -136, - -136, -136, -136, 58, -136, -136, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 158, 58, - 58, 58, 58, 58, 58, 58, 58, -136 - }, - - { - 11, -137, -137, -137, -137, -137, -137, -137, -137, -137, - -137, -137, -137, 58, -137, -137, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 159, 58, 58, -137 - }, - - { - 11, -138, -138, -138, -138, -138, -138, -138, -138, -138, - -138, -138, -138, 58, -138, -138, 58, 160, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -138 - }, - - { - 11, -139, -139, -139, -139, -139, -139, -139, -139, -139, - -139, -139, -139, 58, -139, -139, 58, 58, 58, 58, - 58, 161, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -139 - - }, - - { - 11, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, 58, -140, -140, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 162, 58, - 58, 58, 58, 58, 58, 58, 58, -140 - }, - - { - 11, -141, -141, -141, -141, -141, -141, -141, -141, -141, - -141, -141, -141, 58, -141, -141, 58, 58, 58, 58, - 58, 58, 58, 163, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -141 - }, - - { - 11, -142, -142, -142, -142, -142, -142, -142, -142, -142, - -142, -142, -142, 58, -142, -142, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 164, - 58, 58, 58, 58, 58, 58, 58, -142 - }, - - { - 11, -143, -143, -143, -143, -143, -143, -143, -143, -143, - -143, -143, -143, 58, -143, -143, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 165, 58, 58, 58, 58, -143 - }, - - { - 11, -144, -144, -144, -144, -144, -144, -144, -144, -144, - -144, -144, -144, 58, -144, -144, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 166, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -144 - - }, - - { - 11, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -145, -145, 58, -145, -145, 58, 58, 58, 58, - 167, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -145 - }, - - { - 11, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, -146, 58, -146, -146, 58, 58, 58, 58, - 58, 168, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -146 - }, - - { - 11, -147, -147, -147, -147, -147, -147, -147, -147, -147, - -147, -147, -147, 58, -147, -147, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 169, - 58, 58, 58, 58, 58, 58, 58, -147 - }, - - { - 11, -148, -148, -148, -148, -148, -148, -148, -148, -148, - -148, -148, -148, 58, -148, -148, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -148 - }, - - { - 11, -149, -149, -149, -149, -149, -149, -149, -149, -149, - -149, -149, -149, 58, -149, -149, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 170, 58, - 58, 58, 58, 58, 58, 58, 58, -149 - - }, - - { - 11, -150, -150, -150, -150, -150, -150, -150, -150, -150, - -150, -150, -150, 58, -150, -150, 58, 58, 58, 58, - 58, 171, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -150 + 0, 0, 0, 0, 0, 0, 0 }, { - 11, -151, -151, -151, -151, -151, -151, -151, -151, -151, - -151, -151, -151, 58, -151, -151, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 172, - 58, 58, 58, 58, 58, 58, 58, -151 + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 }, { - 11, -152, -152, -152, -152, -152, -152, -152, -152, -152, - -152, -152, -152, 58, -152, -152, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 173, 58, - 58, 58, 58, 58, 58, 58, 58, -152 + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 }, { - 11, -153, -153, -153, -153, -153, -153, -153, -153, -153, - -153, -153, -153, 58, -153, -153, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 174, 58, 58, -153 + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 }, { - 11, -154, -154, -154, -154, -154, -154, -154, -154, -154, - -154, -154, -154, 58, -154, -154, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -154 + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 }, { - 11, -155, -155, -155, -155, -155, -155, -155, -155, -155, - -155, -155, -155, 58, -155, -155, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 175, 58, 58, 58, 58, -155 + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 }, { - 11, -156, -156, -156, -156, -156, -156, -156, -156, -156, - -156, -156, -156, 58, -156, -156, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 176, 58, 58, -156 + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 }, { - 11, -157, -157, -157, -157, -157, -157, -157, -157, -157, - -157, -157, -157, 58, -157, -157, 58, 58, 58, 58, - - 58, 177, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -157 + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 }, { - 11, -158, -158, -158, -158, -158, -158, -158, -158, -158, - -158, -158, -158, 58, -158, -158, 58, 58, 58, 58, - 58, 58, 58, 178, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -158 + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 }, { - 11, -159, -159, -159, -159, -159, -159, -159, -159, -159, - -159, -159, -159, 58, -159, -159, 58, 179, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -159 + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 }, { - 11, -160, -160, -160, -160, -160, -160, -160, -160, -160, - -160, -160, -160, 58, -160, -160, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 180, 58, - 58, 58, 58, 58, 58, 58, 58, -160 + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 }, { - 11, -161, -161, -161, -161, -161, -161, -161, -161, -161, - -161, -161, -161, 58, -161, -161, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -161 + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 }, { - 11, -162, -162, -162, -162, -162, -162, -162, -162, -162, - -162, -162, -162, 58, -162, -162, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 181, 58, 58, -162 + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 }, { - 11, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, 58, -163, -163, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -163 + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 }, { - 11, -164, -164, -164, -164, -164, -164, -164, -164, -164, - -164, -164, -164, 58, -164, -164, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 182, - 58, 58, 58, 58, 58, 58, 58, -164 + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 }, { - 11, -165, -165, -165, -165, -165, -165, -165, -165, -165, - -165, -165, -165, 58, -165, -165, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 183, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -165 + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 }, { - 11, -166, -166, -166, -166, -166, -166, -166, -166, -166, - -166, -166, -166, 58, -166, -166, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 184, 58, 58, -166 + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 }, { - 11, -167, -167, -167, -167, -167, -167, -167, -167, -167, - -167, -167, -167, 58, -167, -167, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 185, 58, 58, 58, -167 + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 }, { - 11, -168, -168, -168, -168, -168, -168, -168, -168, -168, - -168, -168, -168, 58, -168, -168, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -168 + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 }, { - 11, -169, -169, -169, -169, -169, -169, -169, -169, -169, - -169, -169, -169, 58, -169, -169, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 186, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -169 + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 }, { - 11, -170, -170, -170, -170, -170, -170, -170, -170, -170, - -170, -170, -170, 58, -170, -170, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 187, 58, -170 + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 }, { - 11, -171, -171, -171, -171, -171, -171, -171, -171, -171, - -171, -171, -171, 58, -171, -171, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 188, 58, - 58, 58, 58, 58, 58, 58, 58, -171 + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 }, { - 11, -172, -172, -172, -172, -172, -172, -172, -172, -172, - -172, -172, -172, 58, -172, -172, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 189, 58, - 58, 58, 58, 58, 58, 58, 58, -172 + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 }, { - 11, -173, -173, -173, -173, -173, -173, -173, -173, -173, - -173, -173, -173, 58, -173, -173, 58, 190, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -173 + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 }, { - 11, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -174, -174, 58, -174, -174, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -174 + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 }, { - 11, -175, -175, -175, -175, -175, -175, -175, -175, -175, - -175, -175, -175, 58, -175, -175, 58, 58, 58, 58, - 58, 191, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -175 + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 }, { - 11, -176, -176, -176, -176, -176, -176, -176, -176, -176, - -176, -176, -176, 58, -176, -176, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -176 + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 }, { - 11, -177, -177, -177, -177, -177, -177, -177, -177, -177, - -177, -177, -177, 58, -177, -177, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -177 + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 }, { - 11, -178, -178, -178, -178, -178, -178, -178, -178, -178, - -178, -178, -178, 58, -178, -178, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -178 + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 }, { - 11, -179, -179, -179, -179, -179, -179, -179, -179, -179, - -179, -179, -179, 58, -179, -179, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 192, 58, 58, -179 + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 }, { - 11, -180, -180, -180, -180, -180, -180, -180, -180, -180, - -180, -180, -180, 58, -180, -180, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -180 + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 }, { - 11, -181, -181, -181, -181, -181, -181, -181, -181, -181, - -181, -181, -181, 58, -181, -181, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -181 + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 }, { - 11, -182, -182, -182, -182, -182, -182, -182, -182, -182, - -182, -182, -182, 58, -182, -182, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 193, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -182 + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 }, { - 11, -183, -183, -183, -183, -183, -183, -183, -183, -183, - -183, -183, -183, 58, -183, -183, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 194, 58, 58, 58, -183 + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 }, { - 11, -184, -184, -184, -184, -184, -184, -184, -184, -184, - -184, -184, -184, 58, -184, -184, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -184 + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 }, { - 11, -185, -185, -185, -185, -185, -185, -185, -185, -185, - -185, -185, -185, 58, -185, -185, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -185 + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 }, { - 11, -186, -186, -186, -186, -186, -186, -186, -186, -186, - -186, -186, -186, 58, -186, -186, 58, 58, 58, 195, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -186 + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 }, { - 11, -187, -187, -187, -187, -187, -187, -187, -187, -187, - -187, -187, -187, 58, -187, -187, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -187 + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 }, { - 11, -188, -188, -188, -188, -188, -188, -188, -188, -188, - -188, -188, -188, 58, -188, -188, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 196, 58, -188 + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 }, { - 11, -189, -189, -189, -189, -189, -189, -189, -189, -189, - -189, -189, -189, 58, -189, -189, 58, 58, 58, 58, - 58, 58, 197, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -189 + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 }, { - 11, -190, -190, -190, -190, -190, -190, -190, -190, -190, - -190, -190, -190, 58, -190, -190, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 198, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -190 + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 }, { - 11, -191, -191, -191, -191, -191, -191, -191, -191, -191, - -191, -191, -191, 58, -191, -191, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 199, 58, 58, 58, -191 + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 }, { - 11, -192, -192, -192, -192, -192, -192, -192, -192, -192, - -192, -192, -192, 58, -192, -192, 58, 58, 58, 58, - - 58, 200, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -192 + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 }, { - 11, -193, -193, -193, -193, -193, -193, -193, -193, -193, - -193, -193, -193, 58, -193, -193, 58, 58, 58, 58, - 58, 201, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -193 + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 }, { - 11, -194, -194, -194, -194, -194, -194, -194, -194, -194, - -194, -194, -194, 58, -194, -194, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 202, 58, 58, -194 + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 }, { - 11, -195, -195, -195, -195, -195, -195, -195, -195, -195, - -195, -195, -195, 58, -195, -195, 58, 58, 58, 58, - 58, 203, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -195 + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 }, { - 11, -196, -196, -196, -196, -196, -196, -196, -196, -196, - -196, -196, -196, 58, -196, -196, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -196 + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 }, { - 11, -197, -197, -197, -197, -197, -197, -197, -197, -197, - -197, -197, -197, 58, -197, -197, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 204, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -197 + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 }, { - 11, -198, -198, -198, -198, -198, -198, -198, -198, -198, - -198, -198, -198, 58, -198, -198, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -198 + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 }, { - 11, -199, -199, -199, -199, -199, -199, -199, -199, -199, - -199, -199, -199, 58, -199, -199, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -199 + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 }, { - 11, -200, -200, -200, -200, -200, -200, -200, -200, -200, - -200, -200, -200, 58, -200, -200, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -200 + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 }, { - 11, -201, -201, -201, -201, -201, -201, -201, -201, -201, - -201, -201, -201, 58, -201, -201, 58, 205, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -201 + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 }, { - 11, -202, -202, -202, -202, -202, -202, -202, -202, -202, - -202, -202, -202, 58, -202, -202, 58, 206, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -202 + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 }, { - 11, -203, -203, -203, -203, -203, -203, -203, -203, -203, - -203, -203, -203, 58, -203, -203, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -203 + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 }, { - 11, -204, -204, -204, -204, -204, -204, -204, -204, -204, - -204, -204, -204, 58, -204, -204, 58, 58, 58, 58, - 58, 58, 58, 207, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -204 + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 }, { - 11, -205, -205, -205, -205, -205, -205, -205, -205, -205, - -205, -205, -205, 58, -205, -205, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 208, 58, - 58, 58, 58, 58, 58, 58, 58, -205 + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 }, { - 11, -206, -206, -206, -206, -206, -206, -206, -206, -206, - -206, -206, -206, 58, -206, -206, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 209, 58, 58, -206 + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 }, { - 11, -207, -207, -207, -207, -207, -207, -207, -207, -207, - -207, -207, -207, 58, -207, -207, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -207 + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 }, { - 11, -208, -208, -208, -208, -208, -208, -208, -208, -208, - -208, -208, -208, 58, -208, -208, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -208 + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 }, { - 11, -209, -209, -209, -209, -209, -209, -209, -209, -209, - -209, -209, -209, 58, -209, -209, 58, 58, 58, 58, - 58, 210, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -209 + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 }, { - 11, -210, -210, -210, -210, -210, -210, -210, -210, -210, - -210, -210, -210, 58, -210, -210, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -210 + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 }, } ; @@ -1918,8 +674,8 @@ static void yy_fatal_error (yyconst char msg[] ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 64 -#define YY_END_OF_BUFFER 65 +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -1927,31 +683,14 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[211] = +static yyconst flex_int16_t yy_accept[61] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 65, 5, 4, 3, 2, 36, 37, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 63, 60, 62, 55, 59, 58, 57, 53, 48, 42, - 47, 51, 53, 40, 41, 50, 50, 43, 53, 50, - 50, 53, 4, 3, 2, 2, 1, 35, 35, 35, - 35, 35, 35, 35, 16, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 63, 60, 62, 61, - 55, 54, 57, 56, 44, 51, 38, 50, 50, 52, - 45, 46, 39, 35, 35, 35, 35, 35, 35, 35, - - 35, 35, 30, 29, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 49, 25, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 15, 35, 7, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 17, 35, 35, - 35, 35, 35, 34, 35, 35, 35, 35, 35, 35, - 10, 35, 13, 35, 35, 35, 35, 33, 35, 35, - 35, 35, 35, 22, 35, 32, 9, 31, 35, 26, - 12, 35, 35, 21, 18, 35, 8, 35, 35, 35, - 35, 35, 27, 35, 35, 6, 35, 20, 19, 23, - - 35, 35, 11, 35, 35, 35, 14, 28, 35, 24 + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 } ; static yyconst flex_int32_t yy_ec[256] = @@ -1965,11 +704,11 @@ static yyconst flex_int32_t yy_ec[256] = 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 1, 15, 1, 1, 16, 1, 17, 18, 19, 20, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, - 21, 22, 23, 24, 25, 13, 13, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 13, 13, 36, - 13, 13, 1, 37, 1, 1, 1, 1, 1, 1, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -2014,8 +753,12 @@ char *zconftext; #define START_STRSIZE 16 -char *text; -static char *text_ptr; +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; static int text_size, text_asize; struct buffer { @@ -2028,29 +771,28 @@ struct buffer *current_buf; static int last_ts, first_ts; static void zconf_endhelp(void); -static struct buffer *zconf_endfile(void); +static void zconf_endfile(void); void new_string(void) { text = malloc(START_STRSIZE); text_asize = START_STRSIZE; - text_ptr = text; text_size = 0; - *text_ptr = 0; + *text = 0; } void append_string(const char *str, int size) { int new_size = text_size + size + 1; if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; text = realloc(text, new_size); text_asize = new_size; - text_ptr = text + text_size; } - memcpy(text_ptr, str, size); - text_ptr += size; + memcpy(text + text_size, str, size); text_size += size; - *text_ptr = 0; + text[text_size] = 0; } void alloc_string(const char *str, int size) @@ -2066,11 +808,13 @@ void alloc_string(const char *str, int size) #define STRING 3 #define PARAM 4 +#ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include +#endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * @@ -2254,17 +998,17 @@ do_action: /* This label is used only to access EOF actions. */ { /* beginning of action switch */ case 1: /* rule 1 can match eol */ -YY_RULE_SETUP -current_file->lineno++; - YY_BREAK case 2: +/* rule 2 can match eol */ YY_RULE_SETUP - +{ + current_file->lineno++; + return T_EOL; +} YY_BREAK case 3: -/* rule 3 can match eol */ YY_RULE_SETUP -current_file->lineno++; return T_EOL; + YY_BREAK case 4: YY_RULE_SETUP @@ -2282,175 +1026,63 @@ YY_RULE_SETUP case 6: YY_RULE_SETUP -BEGIN(PARAM); return T_MAINMENU; - YY_BREAK -case 7: -YY_RULE_SETUP -BEGIN(PARAM); return T_MENU; - YY_BREAK -case 8: -YY_RULE_SETUP -BEGIN(PARAM); return T_ENDMENU; - YY_BREAK -case 9: -YY_RULE_SETUP -BEGIN(PARAM); return T_SOURCE; - YY_BREAK -case 10: -YY_RULE_SETUP -BEGIN(PARAM); return T_CHOICE; - YY_BREAK -case 11: -YY_RULE_SETUP -BEGIN(PARAM); return T_ENDCHOICE; - YY_BREAK -case 12: -YY_RULE_SETUP -BEGIN(PARAM); return T_COMMENT; - YY_BREAK -case 13: -YY_RULE_SETUP -BEGIN(PARAM); return T_CONFIG; - YY_BREAK -case 14: -YY_RULE_SETUP -BEGIN(PARAM); return T_MENUCONFIG; - YY_BREAK -case 15: -YY_RULE_SETUP -BEGIN(PARAM); return T_HELP; - YY_BREAK -case 16: -YY_RULE_SETUP -BEGIN(PARAM); return T_IF; - YY_BREAK -case 17: -YY_RULE_SETUP -BEGIN(PARAM); return T_ENDIF; - YY_BREAK -case 18: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEPENDS; - YY_BREAK -case 19: -YY_RULE_SETUP -BEGIN(PARAM); return T_REQUIRES; - YY_BREAK -case 20: -YY_RULE_SETUP -BEGIN(PARAM); return T_OPTIONAL; - YY_BREAK -case 21: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEFAULT; - YY_BREAK -case 22: -YY_RULE_SETUP -BEGIN(PARAM); return T_PROMPT; - YY_BREAK -case 23: -YY_RULE_SETUP -BEGIN(PARAM); return T_TRISTATE; - YY_BREAK -case 24: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEF_TRISTATE; - YY_BREAK -case 25: -YY_RULE_SETUP -BEGIN(PARAM); return T_BOOLEAN; - YY_BREAK -case 26: -YY_RULE_SETUP -BEGIN(PARAM); return T_BOOLEAN; - YY_BREAK -case 27: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEF_BOOLEAN; - YY_BREAK -case 28: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEF_BOOLEAN; - YY_BREAK -case 29: -YY_RULE_SETUP -BEGIN(PARAM); return T_INT; - YY_BREAK -case 30: -YY_RULE_SETUP -BEGIN(PARAM); return T_HEX; - YY_BREAK -case 31: -YY_RULE_SETUP -BEGIN(PARAM); return T_STRING; - YY_BREAK -case 32: -YY_RULE_SETUP -BEGIN(PARAM); return T_SELECT; - YY_BREAK -case 33: -YY_RULE_SETUP -BEGIN(PARAM); return T_SELECT; - YY_BREAK -case 34: -YY_RULE_SETUP -BEGIN(PARAM); return T_RANGE; - YY_BREAK -case 35: -YY_RULE_SETUP { + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } alloc_string(zconftext, zconfleng); zconflval.string = text; return T_WORD; } YY_BREAK -case 36: +case 7: YY_RULE_SETUP YY_BREAK -case 37: -/* rule 37 can match eol */ +case 8: +/* rule 8 can match eol */ YY_RULE_SETUP -current_file->lineno++; BEGIN(INITIAL); +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } YY_BREAK -case 38: +case 9: YY_RULE_SETUP return T_AND; YY_BREAK -case 39: +case 10: YY_RULE_SETUP return T_OR; YY_BREAK -case 40: +case 11: YY_RULE_SETUP return T_OPEN_PAREN; YY_BREAK -case 41: +case 12: YY_RULE_SETUP return T_CLOSE_PAREN; YY_BREAK -case 42: +case 13: YY_RULE_SETUP return T_NOT; YY_BREAK -case 43: +case 14: YY_RULE_SETUP return T_EQUAL; YY_BREAK -case 44: +case 15: YY_RULE_SETUP return T_UNEQUAL; YY_BREAK -case 45: -YY_RULE_SETUP -return T_IF; - YY_BREAK -case 46: -YY_RULE_SETUP -return T_ON; - YY_BREAK -case 47: +case 16: YY_RULE_SETUP { str = zconftext[0]; @@ -2458,33 +1090,38 @@ YY_RULE_SETUP BEGIN(STRING); } YY_BREAK -case 48: -/* rule 48 can match eol */ +case 17: +/* rule 17 can match eol */ YY_RULE_SETUP BEGIN(INITIAL); current_file->lineno++; return T_EOL; YY_BREAK -case 49: +case 18: YY_RULE_SETUP /* ignore */ YY_BREAK -case 50: +case 19: YY_RULE_SETUP { + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } alloc_string(zconftext, zconfleng); zconflval.string = text; return T_WORD; } YY_BREAK -case 51: +case 20: YY_RULE_SETUP /* comment */ YY_BREAK -case 52: -/* rule 52 can match eol */ +case 21: +/* rule 21 can match eol */ YY_RULE_SETUP current_file->lineno++; YY_BREAK -case 53: +case 22: YY_RULE_SETUP YY_BREAK @@ -2494,8 +1131,8 @@ case YY_STATE_EOF(PARAM): } YY_BREAK -case 54: -/* rule 54 can match eol */ +case 23: +/* rule 23 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up zconftext again */ @@ -2506,14 +1143,14 @@ YY_RULE_SETUP return T_WORD_QUOTE; } YY_BREAK -case 55: +case 24: YY_RULE_SETUP { append_string(zconftext, zconfleng); } YY_BREAK -case 56: -/* rule 56 can match eol */ +case 25: +/* rule 25 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up zconftext again */ @@ -2524,13 +1161,13 @@ YY_RULE_SETUP return T_WORD_QUOTE; } YY_BREAK -case 57: +case 26: YY_RULE_SETUP { append_string(zconftext + 1, zconfleng - 1); } YY_BREAK -case 58: +case 27: YY_RULE_SETUP { if (str == zconftext[0]) { @@ -2541,8 +1178,8 @@ YY_RULE_SETUP append_string(zconftext, 1); } YY_BREAK -case 59: -/* rule 59 can match eol */ +case 28: +/* rule 28 can match eol */ YY_RULE_SETUP { printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); @@ -2557,7 +1194,7 @@ case YY_STATE_EOF(STRING): } YY_BREAK -case 60: +case 29: YY_RULE_SETUP { ts = 0; @@ -2582,8 +1219,8 @@ YY_RULE_SETUP } } YY_BREAK -case 61: -/* rule 61 can match eol */ +case 30: +/* rule 30 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up zconftext again */ @@ -2594,15 +1231,15 @@ YY_RULE_SETUP return T_HELPTEXT; } YY_BREAK -case 62: -/* rule 62 can match eol */ +case 31: +/* rule 31 can match eol */ YY_RULE_SETUP { current_file->lineno++; append_string("\n", 1); } YY_BREAK -case 63: +case 32: YY_RULE_SETUP { append_string(zconftext, zconfleng); @@ -2620,15 +1257,15 @@ case YY_STATE_EOF(HELP): case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(COMMAND): { - if (current_buf) { + if (current_file) { zconf_endfile(); - return T_EOF; + return T_EOL; } fclose(zconfin); yyterminate(); } YY_BREAK -case 64: +case 33: YY_RULE_SETUP YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK @@ -3332,16 +1969,16 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to zconflex() will * scan from a @e copy of @a str. - * @param str a NUL-terminated string to scan + * @param yy_str a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * zconf_scan_bytes() instead. */ -YY_BUFFER_STATE zconf_scan_string (yyconst char * str ) +YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str ) { - return zconf_scan_bytes(str,strlen(str) ); + return zconf_scan_bytes(yy_str,strlen(yy_str) ); } /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will @@ -3650,7 +2287,7 @@ void zconf_nextfile(const char *name) current_file = file; } -static struct buffer *zconf_endfile(void) +static void zconf_endfile(void) { struct buffer *parent; @@ -3666,23 +2303,15 @@ static struct buffer *zconf_endfile(void) } free(current_buf); current_buf = parent; - - return parent; } int zconf_lineno(void) { - if (current_buf) - return current_file->lineno - 1; - else - return 0; + return current_pos.lineno; } char *zconf_curname(void) { - if (current_buf) - return current_file->name; - else - return ""; + return current_pos.file ? current_pos.file->name : ""; } diff --git a/scripts/kconfig/mconf.o b/scripts/kconfig/mconf.o index 61fe000c0..6efca8d51 100644 Binary files a/scripts/kconfig/mconf.o and b/scripts/kconfig/mconf.o differ diff --git a/scripts/kconfig/zconf.tab.c b/scripts/kconfig/zconf.tab.c index c9bfdb451..ea7755da8 100644 --- a/scripts/kconfig/zconf.tab.c +++ b/scripts/kconfig/zconf.tab.c @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 1.875a. */ +/* A Bison parser, made by GNU Bison 2.0. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,8 +45,7 @@ /* Using locations. */ #define YYLSP_NEEDED 0 -/* If NAME_PREFIX is specified substitute the variables and functions - names. */ +/* Substitute the variable and function names. */ #define yyparse zconfparse #define yylex zconflex #define yyerror zconferror @@ -79,28 +78,21 @@ T_REQUIRES = 272, T_OPTIONAL = 273, T_PROMPT = 274, - T_DEFAULT = 275, - T_TRISTATE = 276, - T_DEF_TRISTATE = 277, - T_BOOLEAN = 278, - T_DEF_BOOLEAN = 279, - T_STRING = 280, - T_INT = 281, - T_HEX = 282, - T_WORD = 283, - T_WORD_QUOTE = 284, - T_UNEQUAL = 285, - T_EOF = 286, - T_EOL = 287, - T_CLOSE_PAREN = 288, - T_OPEN_PAREN = 289, - T_ON = 290, - T_SELECT = 291, - T_RANGE = 292, - T_OR = 293, - T_AND = 294, - T_EQUAL = 295, - T_NOT = 296 + T_TYPE = 275, + T_DEFAULT = 276, + T_SELECT = 277, + T_RANGE = 278, + T_ON = 279, + T_WORD = 280, + T_WORD_QUOTE = 281, + T_UNEQUAL = 282, + T_CLOSE_PAREN = 283, + T_OPEN_PAREN = 284, + T_EOL = 285, + T_OR = 286, + T_AND = 287, + T_EQUAL = 288, + T_NOT = 289 }; #endif #define T_MAINMENU 258 @@ -120,28 +112,21 @@ #define T_REQUIRES 272 #define T_OPTIONAL 273 #define T_PROMPT 274 -#define T_DEFAULT 275 -#define T_TRISTATE 276 -#define T_DEF_TRISTATE 277 -#define T_BOOLEAN 278 -#define T_DEF_BOOLEAN 279 -#define T_STRING 280 -#define T_INT 281 -#define T_HEX 282 -#define T_WORD 283 -#define T_WORD_QUOTE 284 -#define T_UNEQUAL 285 -#define T_EOF 286 -#define T_EOL 287 -#define T_CLOSE_PAREN 288 -#define T_OPEN_PAREN 289 -#define T_ON 290 -#define T_SELECT 291 -#define T_RANGE 292 -#define T_OR 293 -#define T_AND 294 -#define T_EQUAL 295 -#define T_NOT 296 +#define T_TYPE 275 +#define T_DEFAULT 276 +#define T_SELECT 277 +#define T_RANGE 278 +#define T_ON 279 +#define T_WORD 280 +#define T_WORD_QUOTE 281 +#define T_UNEQUAL 282 +#define T_CLOSE_PAREN 283 +#define T_OPEN_PAREN 284 +#define T_EOL 285 +#define T_OR 286 +#define T_AND 287 +#define T_EQUAL 288 +#define T_NOT 289 @@ -161,6 +146,11 @@ #include #include +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) #define PRINTD 0x0001 @@ -170,12 +160,18 @@ int cdebug = PRINTD; extern int zconflex(void); static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); static void zconferror(const char *err); -static bool zconf_endtoken(int token, int starttoken, int endtoken); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); struct symbol *symbol_hash[257]; +static struct menu *current_menu, *current_entry; + +#define YYDEBUG 0 +#if YYDEBUG #define YYERROR_VERBOSE +#endif /* Enabling traces. */ @@ -194,13 +190,14 @@ struct symbol *symbol_hash[257]; #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) typedef union YYSTYPE { - int token; char *string; + struct file *file; struct symbol *symbol; struct expr *expr; struct menu *menu; + struct kconf_id *id; } YYSTYPE; -/* Line 191 of yacc.c. */ +/* Line 190 of yacc.c. */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -212,27 +209,26 @@ typedef union YYSTYPE { /* Copy the second part of user declarations. */ -#define LKC_DIRECT_LINK -#include "lkc.h" - - -/* Line 214 of yacc.c. */ +/* Line 213 of yacc.c. */ #if ! defined (yyoverflow) || YYERROR_VERBOSE +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + /* The parser invokes alloca or malloc; define the necessary symbols. */ -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca # else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# endif +# define YYSTACK_ALLOC alloca # endif # endif # endif @@ -245,20 +241,20 @@ typedef union YYSTYPE { # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ - || (YYSTYPE_IS_TRIVIAL))) + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - short yyss; + short int yyss; YYSTYPE yyvs; }; @@ -268,13 +264,13 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY -# if 1 < __GNUC__ +# if defined (__GNUC__) && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else @@ -310,26 +306,26 @@ union yyalloc #if defined (__STDC__) || defined (__cplusplus) typedef signed char yysigned_char; #else - typedef short yysigned_char; + typedef short int yysigned_char; #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 2 +#define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 201 +#define YYLAST 264 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 42 +#define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 41 +#define YYNNTS 42 /* YYNRULES -- Number of rules. */ #define YYNRULES 104 /* YYNRULES -- Number of states. */ -#define YYNSTATES 182 +#define YYNSTATES 175 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 296 +#define YYMAXUTOK 289 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -365,79 +361,78 @@ static const unsigned char yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ -static const unsigned short yyprhs[] = +static const unsigned short int yyprhs[] = { - 0, 0, 3, 4, 7, 9, 11, 13, 17, 19, - 21, 23, 26, 28, 30, 32, 34, 36, 38, 42, - 45, 49, 52, 53, 56, 59, 62, 65, 69, 74, - 78, 83, 87, 91, 95, 100, 105, 110, 116, 119, - 122, 124, 128, 131, 132, 135, 138, 141, 144, 149, - 153, 157, 160, 165, 166, 169, 173, 175, 179, 182, - 183, 186, 189, 192, 196, 199, 201, 205, 208, 209, - 212, 215, 218, 222, 226, 228, 232, 235, 238, 241, - 242, 245, 248, 253, 257, 261, 262, 265, 267, 269, - 272, 275, 278, 280, 282, 283, 286, 288, 292, 296, - 300, 303, 307, 311, 313 + 0, 0, 3, 5, 6, 9, 12, 15, 20, 23, + 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, + 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, + 81, 84, 85, 88, 91, 94, 97, 100, 104, 109, + 114, 119, 125, 128, 131, 133, 137, 138, 141, 144, + 147, 150, 153, 158, 162, 165, 170, 171, 174, 178, + 180, 184, 185, 188, 191, 194, 198, 201, 203, 207, + 208, 211, 214, 217, 221, 225, 228, 231, 234, 235, + 238, 241, 244, 249, 253, 257, 258, 261, 263, 265, + 268, 271, 274, 276, 279, 280, 283, 285, 289, 293, + 297, 300, 304, 308, 310 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { - 43, 0, -1, -1, 43, 44, -1, 45, -1, 55, - -1, 66, -1, 3, 77, 79, -1, 5, -1, 15, - -1, 8, -1, 1, 79, -1, 61, -1, 71, -1, - 47, -1, 49, -1, 69, -1, 79, -1, 10, 28, - 32, -1, 46, 50, -1, 11, 28, 32, -1, 48, - 50, -1, -1, 50, 51, -1, 50, 75, -1, 50, - 73, -1, 50, 32, -1, 21, 76, 32, -1, 22, - 81, 80, 32, -1, 23, 76, 32, -1, 24, 81, - 80, 32, -1, 26, 76, 32, -1, 27, 76, 32, - -1, 25, 76, 32, -1, 19, 77, 80, 32, -1, - 20, 81, 80, 32, -1, 36, 28, 80, 32, -1, - 37, 82, 82, 80, 32, -1, 7, 32, -1, 52, - 56, -1, 78, -1, 53, 58, 54, -1, 53, 58, - -1, -1, 56, 57, -1, 56, 75, -1, 56, 73, - -1, 56, 32, -1, 19, 77, 80, 32, -1, 21, - 76, 32, -1, 23, 76, 32, -1, 18, 32, -1, - 20, 28, 80, 32, -1, -1, 58, 45, -1, 14, - 81, 32, -1, 78, -1, 59, 62, 60, -1, 59, - 62, -1, -1, 62, 45, -1, 62, 66, -1, 62, - 55, -1, 4, 77, 32, -1, 63, 74, -1, 78, - -1, 64, 67, 65, -1, 64, 67, -1, -1, 67, - 45, -1, 67, 66, -1, 67, 55, -1, 67, 1, - 32, -1, 6, 77, 32, -1, 68, -1, 9, 77, - 32, -1, 70, 74, -1, 12, 32, -1, 72, 13, - -1, -1, 74, 75, -1, 74, 32, -1, 16, 35, - 81, 32, -1, 16, 81, 32, -1, 17, 81, 32, - -1, -1, 77, 80, -1, 28, -1, 29, -1, 5, - 79, -1, 8, 79, -1, 15, 79, -1, 32, -1, - 31, -1, -1, 14, 81, -1, 82, -1, 82, 40, - 82, -1, 82, 30, 82, -1, 34, 81, 33, -1, - 41, 81, -1, 81, 38, 81, -1, 81, 39, 81, - -1, 28, -1, 29, -1 + 36, 0, -1, 37, -1, -1, 37, 39, -1, 37, + 50, -1, 37, 61, -1, 37, 3, 71, 73, -1, + 37, 72, -1, 37, 25, 1, 30, -1, 37, 38, + 1, 30, -1, 37, 1, 30, -1, 16, -1, 19, + -1, 20, -1, 22, -1, 18, -1, 23, -1, 21, + -1, 30, -1, 56, -1, 65, -1, 42, -1, 44, + -1, 63, -1, 25, 1, 30, -1, 1, 30, -1, + 10, 25, 30, -1, 41, 45, -1, 11, 25, 30, + -1, 43, 45, -1, -1, 45, 46, -1, 45, 69, + -1, 45, 67, -1, 45, 40, -1, 45, 30, -1, + 20, 70, 30, -1, 19, 71, 74, 30, -1, 21, + 75, 74, 30, -1, 22, 25, 74, 30, -1, 23, + 76, 76, 74, 30, -1, 7, 30, -1, 47, 51, + -1, 72, -1, 48, 53, 49, -1, -1, 51, 52, + -1, 51, 69, -1, 51, 67, -1, 51, 30, -1, + 51, 40, -1, 19, 71, 74, 30, -1, 20, 70, + 30, -1, 18, 30, -1, 21, 25, 74, 30, -1, + -1, 53, 39, -1, 14, 75, 73, -1, 72, -1, + 54, 57, 55, -1, -1, 57, 39, -1, 57, 61, + -1, 57, 50, -1, 4, 71, 30, -1, 58, 68, + -1, 72, -1, 59, 62, 60, -1, -1, 62, 39, + -1, 62, 61, -1, 62, 50, -1, 6, 71, 30, + -1, 9, 71, 30, -1, 64, 68, -1, 12, 30, + -1, 66, 13, -1, -1, 68, 69, -1, 68, 30, + -1, 68, 40, -1, 16, 24, 75, 30, -1, 16, + 75, 30, -1, 17, 75, 30, -1, -1, 71, 74, + -1, 25, -1, 26, -1, 5, 30, -1, 8, 30, + -1, 15, 30, -1, 30, -1, 73, 30, -1, -1, + 14, 75, -1, 76, -1, 76, 33, 76, -1, 76, + 27, 76, -1, 29, 75, 28, -1, 34, 75, -1, + 75, 31, 75, -1, 75, 32, 75, -1, 25, -1, + 26, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned short yyrline[] = +static const unsigned short int yyrline[] = { - 0, 94, 94, 95, 98, 99, 100, 101, 102, 103, - 104, 105, 109, 110, 111, 112, 113, 114, 120, 128, - 134, 142, 152, 154, 155, 156, 157, 160, 166, 173, - 179, 186, 192, 198, 204, 210, 216, 222, 230, 239, - 245, 254, 255, 261, 263, 264, 265, 266, 269, 275, - 281, 287, 293, 299, 301, 306, 315, 324, 325, 331, - 333, 334, 335, 340, 347, 353, 362, 363, 369, 371, - 372, 373, 374, 377, 383, 390, 397, 404, 410, 417, - 418, 419, 422, 427, 432, 440, 442, 447, 448, 451, - 452, 453, 457, 457, 459, 460, 463, 464, 465, 466, - 467, 468, 469, 472, 473 + 0, 103, 103, 105, 107, 108, 109, 110, 111, 112, + 113, 117, 121, 121, 121, 121, 121, 121, 121, 125, + 126, 127, 128, 129, 130, 134, 135, 141, 149, 155, + 163, 173, 175, 176, 177, 178, 179, 182, 190, 196, + 206, 212, 220, 229, 234, 242, 245, 247, 248, 249, + 250, 251, 254, 260, 271, 277, 287, 289, 294, 302, + 310, 313, 315, 316, 317, 322, 329, 334, 342, 345, + 347, 348, 349, 352, 360, 367, 374, 380, 387, 389, + 390, 391, 394, 399, 404, 412, 414, 419, 420, 423, + 424, 425, 429, 430, 433, 434, 437, 438, 439, 440, + 441, 442, 443, 446, 447 }; #endif @@ -446,67 +441,65 @@ static const unsigned short yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", - "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", - "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", - "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", - "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT", - "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL", - "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR", - "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", - "common_block", "config_entry_start", "config_stmt", - "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", - "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", - "choice_option_list", "choice_option", "choice_block", "if", "if_end", - "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", - "menu_block", "source", "source_stmt", "comment", "comment_stmt", - "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", - "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0 + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", + "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt", + "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", + "choice_option_list", "choice_option", "choice_block", "if_entry", + "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end", + "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt", + "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", + "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ -static const unsigned short yytoknum[] = +static const unsigned short int yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296 + 285, 286, 287, 288, 289 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { - 0, 42, 43, 43, 44, 44, 44, 44, 44, 44, - 44, 44, 45, 45, 45, 45, 45, 45, 46, 47, - 48, 49, 50, 50, 50, 50, 50, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 52, 53, - 54, 55, 55, 56, 56, 56, 56, 56, 57, 57, - 57, 57, 57, 58, 58, 59, 60, 61, 61, 62, - 62, 62, 62, 63, 64, 65, 66, 66, 67, 67, - 67, 67, 67, 68, 69, 70, 71, 72, 73, 74, - 74, 74, 75, 75, 75, 76, 76, 77, 77, 78, - 78, 78, 79, 79, 80, 80, 81, 81, 81, 81, - 81, 81, 81, 82, 82 + 0, 35, 36, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, + 39, 39, 39, 39, 39, 40, 40, 41, 42, 43, + 44, 45, 45, 45, 45, 45, 45, 46, 46, 46, + 46, 46, 47, 48, 49, 50, 51, 51, 51, 51, + 51, 51, 52, 52, 52, 52, 53, 53, 54, 55, + 56, 57, 57, 57, 57, 58, 59, 60, 61, 62, + 62, 62, 62, 63, 64, 65, 66, 67, 68, 68, + 68, 68, 69, 69, 69, 70, 70, 71, 71, 72, + 72, 72, 73, 73, 74, 74, 75, 75, 75, 75, + 75, 75, 75, 76, 76 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { - 0, 2, 0, 2, 1, 1, 1, 3, 1, 1, - 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, - 3, 2, 0, 2, 2, 2, 2, 3, 4, 3, - 4, 3, 3, 3, 4, 4, 4, 5, 2, 2, - 1, 3, 2, 0, 2, 2, 2, 2, 4, 3, - 3, 2, 4, 0, 2, 3, 1, 3, 2, 0, - 2, 2, 2, 3, 2, 1, 3, 2, 0, 2, - 2, 2, 3, 3, 1, 3, 2, 2, 2, 0, + 0, 2, 1, 0, 2, 2, 2, 4, 2, 4, + 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, + 2, 0, 2, 2, 2, 2, 2, 3, 4, 4, + 4, 5, 2, 2, 1, 3, 0, 2, 2, 2, + 2, 2, 4, 3, 2, 4, 0, 2, 3, 1, + 3, 0, 2, 2, 2, 3, 2, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, 2, 2, 4, 3, 3, 0, 2, 1, 1, 2, - 2, 2, 1, 1, 0, 2, 1, 3, 3, 3, + 2, 2, 1, 2, 0, 2, 1, 3, 3, 3, 2, 3, 3, 1, 1 }; @@ -515,151 +508,160 @@ static const unsigned char yyr2[] = means the default is an error. */ static const unsigned char yydefact[] = { - 2, 0, 1, 0, 0, 0, 8, 0, 0, 10, - 0, 0, 0, 0, 9, 93, 92, 3, 4, 22, - 14, 22, 15, 43, 53, 5, 59, 12, 79, 68, - 6, 74, 16, 79, 13, 17, 11, 87, 88, 0, - 0, 0, 38, 0, 0, 0, 103, 104, 0, 0, - 0, 96, 19, 21, 39, 42, 58, 64, 0, 76, - 7, 63, 73, 75, 18, 20, 0, 100, 55, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, - 85, 0, 85, 85, 85, 26, 0, 0, 23, 0, - 25, 24, 0, 0, 0, 85, 85, 47, 44, 46, - 45, 0, 0, 0, 54, 41, 40, 60, 62, 57, - 61, 56, 81, 80, 0, 69, 71, 66, 70, 65, - 99, 101, 102, 98, 97, 77, 0, 0, 0, 94, - 94, 0, 94, 94, 0, 94, 0, 0, 0, 94, - 0, 78, 51, 94, 94, 0, 0, 89, 90, 91, - 72, 0, 83, 84, 0, 0, 0, 27, 86, 0, - 29, 0, 33, 31, 32, 0, 94, 0, 0, 49, - 50, 82, 95, 34, 35, 28, 30, 36, 0, 48, - 52, 37 + 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, + 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, + 23, 46, 56, 5, 61, 20, 78, 69, 6, 24, + 78, 21, 8, 11, 87, 88, 0, 0, 89, 0, + 42, 90, 0, 0, 0, 103, 104, 0, 0, 0, + 96, 91, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 92, 7, 65, 73, 74, 27, 29, 0, + 100, 0, 0, 58, 0, 0, 9, 10, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 0, 36, 35, + 32, 0, 34, 33, 0, 0, 85, 0, 50, 51, + 47, 49, 48, 57, 45, 44, 62, 64, 60, 63, + 59, 80, 81, 79, 70, 72, 68, 71, 67, 93, + 99, 101, 102, 98, 97, 26, 76, 0, 0, 0, + 94, 0, 94, 94, 94, 0, 0, 77, 54, 94, + 0, 94, 0, 83, 84, 0, 0, 37, 86, 0, + 0, 94, 25, 0, 53, 0, 82, 95, 38, 39, + 40, 0, 52, 55, 41 }; /* YYDEFGOTO[NTERM-NUM]. */ -static const short yydefgoto[] = +static const short int yydefgoto[] = { - -1, 1, 17, 18, 19, 20, 21, 22, 52, 88, - 23, 24, 105, 25, 54, 98, 55, 26, 109, 27, - 56, 28, 29, 117, 30, 58, 31, 32, 33, 34, - 89, 90, 57, 91, 131, 132, 106, 35, 155, 50, - 51 + -1, 1, 2, 25, 26, 99, 27, 28, 29, 30, + 64, 100, 31, 32, 114, 33, 66, 110, 67, 34, + 118, 35, 68, 36, 37, 126, 38, 70, 39, 40, + 41, 101, 102, 69, 103, 141, 142, 42, 73, 156, + 59, 60 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -99 -static const short yypact[] = +#define YYPACT_NINF -78 +static const short int yypact[] = { - -99, 48, -99, 38, 46, 46, -99, 46, -29, -99, - 46, -17, -3, -11, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, -99, -99, -99, -99, -99, 38, - 12, 15, -99, 18, 51, 62, -99, -99, -11, -11, - 4, -24, 138, 138, 160, 121, 110, -4, 81, -4, - -99, -99, -99, -99, -99, -99, -19, -99, -99, -11, - -11, 70, 70, 73, 32, -11, 46, -11, 46, -11, - 46, -11, 46, 46, 46, -99, 36, 70, -99, 95, - -99, -99, 96, 46, 106, 46, 46, -99, -99, -99, - -99, 38, 38, 38, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, 112, -99, -99, -99, -99, -99, - -99, 117, -99, -99, -99, -99, -11, 33, 65, 131, - 1, 119, 131, 1, 136, 1, 153, 154, 155, 131, - 70, -99, -99, 131, 131, 156, 157, -99, -99, -99, - -99, 101, -99, -99, -11, 158, 159, -99, -99, 161, - -99, 162, -99, -99, -99, 163, 131, 164, 165, -99, - -99, -99, 99, -99, -99, -99, -99, -99, 166, -99, - -99, -99 + -78, 2, 159, -78, -21, 0, 0, -12, 0, 1, + 4, 0, 27, 38, 60, 58, -78, -78, -78, -78, + -78, -78, -78, 100, -78, 104, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, 86, 113, -78, 114, + -78, -78, 125, 127, 128, -78, -78, 60, 60, 210, + 65, -78, 141, 142, 39, 103, 182, 200, 6, 66, + 6, 131, -78, 146, -78, -78, -78, -78, -78, 196, + -78, 60, 60, 146, 40, 40, -78, -78, 155, 156, + -2, 60, 0, 0, 60, 105, 40, 194, -78, -78, + -78, 206, -78, -78, 183, 0, 0, 195, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, 197, -78, -78, -78, -78, -78, 60, 213, 216, + 212, 203, 212, 190, 212, 40, 208, -78, -78, 212, + 222, 212, 219, -78, -78, 60, 223, -78, -78, 224, + 225, 212, -78, 226, -78, 227, -78, 47, -78, -78, + -78, 228, -78, -78, -78 }; /* YYPGOTO[NTERM-NUM]. */ -static const short yypgoto[] = +static const short int yypgoto[] = { - -99, -99, -99, 111, -99, -99, -99, -99, 178, -99, - -99, -99, -99, 91, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, 115, -99, -99, -99, -99, -99, - -99, 146, 168, 89, 27, 0, 126, -1, -98, -48, - -63 + -78, -78, -78, -78, 164, -36, -78, -78, -78, -78, + 230, -78, -78, -78, -78, 29, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, 59, -78, -78, -78, + -78, -78, 198, 220, 24, 157, -5, 169, 202, 74, + -53, -77 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -68 -static const short yytable[] = +#define YYTABLE_NINF -76 +static const short int yytable[] = { - 66, 67, 36, 42, 39, 40, 71, 41, 123, 124, - 43, 44, 74, 75, 120, 154, 72, 46, 47, 69, - 70, 121, 122, 48, 140, 45, 127, 128, 112, 130, - 49, 133, 156, 135, 158, 159, 68, 161, 60, 69, - 70, 165, 69, 70, 61, 167, 168, 62, 2, 3, - 63, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 46, 47, 13, 14, 139, 152, 48, 126, 178, 15, - 16, 69, 70, 49, 37, 38, 129, 166, 151, 15, - 16, -67, 114, 64, -67, 5, 101, 7, 8, 102, - 10, 11, 12, 143, 65, 13, 103, 153, 46, 47, - 147, 148, 149, 69, 70, 125, 172, 134, 141, 136, - 137, 138, 15, 16, 5, 101, 7, 8, 102, 10, - 11, 12, 145, 146, 13, 103, 101, 7, 142, 102, - 10, 11, 12, 171, 144, 13, 103, 69, 70, 69, - 70, 15, 16, 100, 150, 154, 113, 108, 113, 116, - 73, 157, 15, 16, 74, 75, 70, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 104, 107, 160, 115, - 85, 110, 73, 118, 86, 87, 74, 75, 92, 93, - 94, 95, 111, 96, 119, 162, 163, 164, 169, 170, - 173, 174, 97, 175, 176, 177, 179, 180, 181, 53, - 99, 59 + 46, 47, 3, 49, 79, 80, 52, 133, 134, 43, + 6, 7, 8, 9, 10, 11, 12, 13, 48, 145, + 14, 15, 137, 55, 56, 44, 45, 57, 131, 132, + 109, 50, 58, 122, 51, 122, 24, 138, 139, -28, + 88, 143, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 89, 53, -28, -28, 90, 91, -28, 92, 93, + 94, 95, 96, 54, 97, 55, 56, 88, 161, 98, + -66, -66, -66, -66, -66, -66, -66, -66, 81, 82, + -66, -66, 90, 91, 152, 55, 56, 140, 61, 57, + 112, 97, 84, 123, 58, 123, 121, 117, 85, 125, + 149, 62, 167, -30, 88, 63, -30, -30, -30, -30, + -30, -30, -30, -30, -30, 89, 72, -30, -30, 90, + 91, -30, 92, 93, 94, 95, 96, 119, 97, 127, + 144, -75, 88, 98, -75, -75, -75, -75, -75, -75, + -75, -75, -75, 74, 75, -75, -75, 90, 91, -75, + -75, -75, -75, -75, -75, 76, 97, 77, 78, -2, + 4, 121, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 86, 87, 14, 15, 16, 129, 17, 18, 19, + 20, 21, 22, 88, 23, 135, 136, -43, -43, 24, + -43, -43, -43, -43, 89, 146, -43, -43, 90, 91, + 104, 105, 106, 107, 155, 7, 8, 97, 10, 11, + 12, 13, 108, 148, 14, 15, 158, 159, 160, 147, + 151, 81, 82, 163, 130, 165, 155, 81, 82, 82, + 24, 113, 116, 157, 124, 171, 115, 120, 162, 128, + 72, 81, 82, 153, 81, 82, 154, 81, 82, 166, + 81, 82, 164, 168, 169, 170, 172, 173, 174, 65, + 71, 83, 0, 150, 111 }; -static const unsigned char yycheck[] = +static const short int yycheck[] = { - 48, 49, 3, 32, 4, 5, 30, 7, 71, 72, - 10, 28, 16, 17, 33, 14, 40, 28, 29, 38, - 39, 69, 70, 34, 87, 28, 74, 75, 32, 77, - 41, 79, 130, 81, 132, 133, 32, 135, 39, 38, - 39, 139, 38, 39, 32, 143, 144, 32, 0, 1, - 32, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 28, 29, 14, 15, 28, 32, 34, 35, 166, 31, - 32, 38, 39, 41, 28, 29, 76, 140, 126, 31, - 32, 0, 1, 32, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 93, 32, 14, 15, 32, 28, 29, - 101, 102, 103, 38, 39, 32, 154, 80, 13, 82, - 83, 84, 31, 32, 4, 5, 6, 7, 8, 9, - 10, 11, 95, 96, 14, 15, 5, 6, 32, 8, - 9, 10, 11, 32, 28, 14, 15, 38, 39, 38, - 39, 31, 32, 54, 32, 14, 57, 56, 59, 58, - 12, 32, 31, 32, 16, 17, 39, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 55, 56, 32, 58, - 32, 56, 12, 58, 36, 37, 16, 17, 18, 19, - 20, 21, 56, 23, 58, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 21, - 54, 33 + 5, 6, 0, 8, 57, 58, 11, 84, 85, 30, + 4, 5, 6, 7, 8, 9, 10, 11, 30, 96, + 14, 15, 24, 25, 26, 25, 26, 29, 81, 82, + 66, 30, 34, 69, 30, 71, 30, 90, 91, 0, + 1, 94, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 25, 25, 25, 26, 1, 145, 30, + 4, 5, 6, 7, 8, 9, 10, 11, 31, 32, + 14, 15, 16, 17, 137, 25, 26, 92, 30, 29, + 66, 25, 27, 69, 34, 71, 30, 68, 33, 70, + 105, 1, 155, 0, 1, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 30, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 68, 25, 70, + 25, 0, 1, 30, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 30, 30, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 30, 25, 30, 30, 0, + 1, 30, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 30, 30, 14, 15, 16, 30, 18, 19, 20, + 21, 22, 23, 1, 25, 30, 30, 5, 6, 30, + 8, 9, 10, 11, 12, 1, 14, 15, 16, 17, + 18, 19, 20, 21, 14, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 142, 143, 144, 13, + 25, 31, 32, 149, 28, 151, 14, 31, 32, 32, + 30, 67, 68, 30, 70, 161, 67, 68, 30, 70, + 30, 31, 32, 30, 31, 32, 30, 31, 32, 30, + 31, 32, 30, 30, 30, 30, 30, 30, 30, 29, + 40, 59, -1, 106, 66 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { - 0, 43, 0, 1, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 14, 15, 31, 32, 44, 45, 46, - 47, 48, 49, 52, 53, 55, 59, 61, 63, 64, - 66, 68, 69, 70, 71, 79, 79, 28, 29, 77, - 77, 77, 32, 77, 28, 28, 28, 29, 34, 41, - 81, 82, 50, 50, 56, 58, 62, 74, 67, 74, - 79, 32, 32, 32, 32, 32, 81, 81, 32, 38, - 39, 30, 40, 12, 16, 17, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 32, 36, 37, 51, 72, - 73, 75, 18, 19, 20, 21, 23, 32, 57, 73, - 75, 5, 8, 15, 45, 54, 78, 45, 55, 60, - 66, 78, 32, 75, 1, 45, 55, 65, 66, 78, - 33, 81, 81, 82, 82, 32, 35, 81, 81, 77, - 81, 76, 77, 81, 76, 81, 76, 76, 76, 28, - 82, 13, 32, 77, 28, 76, 76, 79, 79, 79, - 32, 81, 32, 32, 14, 80, 80, 32, 80, 80, - 32, 80, 32, 32, 32, 80, 82, 80, 80, 32, - 32, 32, 81, 32, 32, 32, 32, 32, 80, 32, - 32, 32 + 0, 36, 37, 0, 1, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 14, 15, 16, 18, 19, 20, + 21, 22, 23, 25, 30, 38, 39, 41, 42, 43, + 44, 47, 48, 50, 54, 56, 58, 59, 61, 63, + 64, 65, 72, 30, 25, 26, 71, 71, 30, 71, + 30, 30, 71, 25, 25, 25, 26, 29, 34, 75, + 76, 30, 1, 1, 45, 45, 51, 53, 57, 68, + 62, 68, 30, 73, 30, 30, 30, 30, 30, 75, + 75, 31, 32, 73, 27, 33, 30, 30, 1, 12, + 16, 17, 19, 20, 21, 22, 23, 25, 30, 40, + 46, 66, 67, 69, 18, 19, 20, 21, 30, 40, + 52, 67, 69, 39, 49, 72, 39, 50, 55, 61, + 72, 30, 40, 69, 39, 50, 60, 61, 72, 30, + 28, 75, 75, 76, 76, 30, 30, 24, 75, 75, + 71, 70, 71, 75, 25, 76, 1, 13, 30, 71, + 70, 25, 75, 30, 30, 14, 74, 30, 74, 74, + 74, 76, 30, 74, 30, 74, 30, 75, 30, 30, + 30, 74, 30, 30, 30 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) @@ -685,7 +687,7 @@ static const unsigned char yystos[] = #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 +#define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily @@ -713,20 +715,53 @@ do \ } \ while (0) + #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). */ +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.first_line = Rhs[1].first_line; \ - Current.first_column = Rhs[1].first_column; \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) #endif + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM @@ -749,36 +784,30 @@ do { \ YYFPRINTF Args; \ } while (0) -# define YYDSYMPRINT(Args) \ -do { \ - if (yydebug) \ - yysymprint Args; \ -} while (0) - -# define YYDSYMPRINTF(Title, Token, Value, Location) \ +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yysymprint (stderr, \ - Token, Value); \ + Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (cinluded). | +| TOP (included). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void -yy_stack_print (short *bottom, short *top) +yy_stack_print (short int *bottom, short int *top) #else static void yy_stack_print (bottom, top) - short *bottom; - short *top; + short int *bottom; + short int *top; #endif { YYFPRINTF (stderr, "Stack now"); @@ -808,9 +837,9 @@ yy_reduce_print (yyrule) #endif { int yyi; - unsigned int yylineno = yyrline[yyrule]; + unsigned int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", - yyrule - 1, yylineno); + yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); @@ -828,8 +857,7 @@ do { \ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) -# define YYDSYMPRINT(Args) -# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ @@ -847,10 +875,6 @@ int yydebug; SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#if YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif - #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif @@ -932,15 +956,15 @@ yysymprint (yyoutput, yytype, yyvaluep) (void) yyvaluep; if (yytype < YYNTOKENS) - { - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); -# ifdef YYPRINT - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - } + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif switch (yytype) { default: @@ -956,10 +980,11 @@ yysymprint (yyoutput, yytype, yyvaluep) #if defined (__STDC__) || defined (__cplusplus) static void -yydestruct (int yytype, YYSTYPE *yyvaluep) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void -yydestruct (yytype, yyvaluep) +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif @@ -967,8 +992,42 @@ yydestruct (yytype, yyvaluep) /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + switch (yytype) { + case 48: /* choice_entry */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 54: /* if_entry */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 59: /* menu_entry */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; default: break; @@ -994,10 +1053,10 @@ int yyparse (); -/* The lookahead symbol. */ +/* The look-ahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ +/* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ @@ -1033,7 +1092,7 @@ yyparse () int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ + /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; /* Three stacks and their tools: @@ -1045,9 +1104,9 @@ yyparse () to reallocate them elsewhere. */ /* The state stack. */ - short yyssa[YYINITDEPTH]; - short *yyss = yyssa; - register short *yyssp; + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; @@ -1084,6 +1143,9 @@ yyparse () yyssp = yyss; yyvsp = yyvs; + + yyvsp[0] = yylval; + goto yysetstate; /*------------------------------------------------------------. @@ -1109,7 +1171,7 @@ yyparse () these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; + short int *yyss1 = yyss; /* Each stack pointer address is followed by the size of the @@ -1137,7 +1199,7 @@ yyparse () yystacksize = YYMAXDEPTH; { - short *yyss1 = yyss; + short int *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) @@ -1173,18 +1235,18 @@ yyparse () yybackup: /* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ +/* Read a look-ahead token if we need one and don't already have one. */ /* yyresume: */ - /* First try to decide what to do without reference to lookahead token. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -1199,7 +1261,7 @@ yybackup: else { yytoken = YYTRANSLATE (yychar); - YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to @@ -1219,8 +1281,8 @@ yybackup: if (yyn == YYFINAL) YYACCEPT; - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) @@ -1271,155 +1333,123 @@ yyreduce: { case 8: - { zconfprint("unexpected 'endmenu' statement"); ;} + { zconf_error("unexpected end statement"); ;} break; case 9: - { zconfprint("unexpected 'endif' statement"); ;} + { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;} break; case 10: - { zconfprint("unexpected 'endchoice' statement"); ;} + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name); +;} break; case 11: - { zconfprint("syntax error"); yyerrok; ;} + { zconf_error("invalid statement"); ;} break; - case 18: + case 25: - { - struct symbol *sym = sym_lookup(yyvsp[-1].string, 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); -;} + { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); ;} break; - case 19: + case 26: - { - menu_end_entry(); - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -;} + { zconf_error("invalid option"); ;} break; - case 20: + case 27: { - struct symbol *sym = sym_lookup(yyvsp[-1].string, 0); + struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); sym->flags |= SYMBOL_OPTIONAL; menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); ;} break; - case 21: + case 28: { - if (current_entry->prompt) - current_entry->prompt->type = P_MENU; - else - zconfprint("warning: menuconfig statement without prompt"); menu_end_entry(); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); ;} break; - case 27: - - { - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 28: - - { - menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); -;} - break; - case 29: { - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); + struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); ;} break; case 30: { - menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 31: - - { - menu_set_type(S_INT); - printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 32: - - { - menu_set_type(S_HEX); - printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); ;} break; - case 33: + case 37: { - menu_set_type(S_STRING); - printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); + menu_set_type((yyvsp[-2].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-2].id)->stype); ;} break; - case 34: + case 38: { - menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr); + menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); ;} break; - case 35: + case 39: { - menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); - printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); + menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); + if ((yyvsp[-3].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[-3].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-3].id)->stype); ;} break; - case 36: + case 40: { - menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); ;} break; - case 37: + case 41: { - menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,yyvsp[-3].symbol, yyvsp[-2].symbol), yyvsp[-1].expr); + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); ;} break; - case 38: + case 42: { struct symbol *sym = sym_lookup(NULL, 0); @@ -1430,57 +1460,45 @@ yyreduce: ;} break; - case 39: + case 43: { - menu_end_entry(); - menu_add_menu(); + (yyval.menu) = menu_add_menu(); ;} break; - case 40: + case 44: { - if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) { + if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); } ;} break; - case 42: - - { - printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -;} - break; - - case 48: + case 52: { - menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr); + menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); ;} break; - case 49: + case 53: { - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); + if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[-2].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-2].id)->stype); + } else + YYERROR; ;} break; - case 50: - - { - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 51: + case 54: { current_entry->sym->flags |= SYMBOL_OPTIONAL; @@ -1488,115 +1506,89 @@ yyreduce: ;} break; - case 52: + case 55: { - menu_add_symbol(P_DEFAULT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); - printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); + if ((yyvsp[-3].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; ;} break; - case 55: + case 58: { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); - menu_add_dep(yyvsp[-1].expr); - menu_end_entry(); - menu_add_menu(); + menu_add_dep((yyvsp[-1].expr)); + (yyval.menu) = menu_add_menu(); ;} break; - case 56: + case 59: { - if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) { + if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); } ;} break; - case 58: - - { - printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -;} - break; - - case 63: + case 65: { menu_add_entry(NULL); - menu_add_prop(P_MENU, yyvsp[-1].string, NULL, NULL); + menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL); printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); ;} break; - case 64: + case 66: { - menu_end_entry(); - menu_add_menu(); + (yyval.menu) = menu_add_menu(); ;} break; - case 65: + case 67: { - if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) { + if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); } ;} break; - case 67: - - { - printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -;} - break; - - case 72: - - { zconfprint("invalid menu option"); yyerrok; ;} - break; - case 73: { - yyval.string = yyvsp[-1].string; - printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); + zconf_nextfile((yyvsp[-1].string)); ;} break; case 74: - { - zconf_nextfile(yyvsp[0].string); -;} - break; - - case 75: - { menu_add_entry(NULL); - menu_add_prop(P_COMMENT, yyvsp[-1].string, NULL, NULL); + menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL); printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); ;} break; - case 76: + case 75: { menu_end_entry(); ;} break; - case 77: + case 76: { printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); @@ -1604,17 +1596,17 @@ yyreduce: ;} break; - case 78: + case 77: { - current_entry->sym->help = yyvsp[0].string; + current_entry->sym->help = (yyvsp[0].string); ;} break; case 82: { - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1622,7 +1614,7 @@ yyreduce: case 83: { - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1630,7 +1622,7 @@ yyreduce: case 84: { - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1638,84 +1630,84 @@ yyreduce: case 86: { - menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr); + menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr)); ;} break; case 89: - { yyval.token = T_ENDMENU; ;} + { (yyval.id) = (yyvsp[-1].id); ;} break; case 90: - { yyval.token = T_ENDCHOICE; ;} + { (yyval.id) = (yyvsp[-1].id); ;} break; case 91: - { yyval.token = T_ENDIF; ;} + { (yyval.id) = (yyvsp[-1].id); ;} break; case 94: - { yyval.expr = NULL; ;} + { (yyval.expr) = NULL; ;} break; case 95: - { yyval.expr = yyvsp[0].expr; ;} + { (yyval.expr) = (yyvsp[0].expr); ;} break; case 96: - { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;} + { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;} break; case 97: - { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; case 98: - { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; case 99: - { yyval.expr = yyvsp[-1].expr; ;} + { (yyval.expr) = (yyvsp[-1].expr); ;} break; case 100: - { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;} + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;} break; case 101: - { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;} + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 102: - { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;} + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 103: - { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;} + { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;} break; case 104: - { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;} + { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;} break; } -/* Line 999 of yacc.c. */ +/* Line 1037 of yacc.c. */ yyvsp -= yylen; @@ -1757,18 +1749,33 @@ yyerrlab: { YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); + const char* yyprefix; char *yymsg; - int yyx, yycount; + int yyx; - yycount = 0; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("syntax error, unexpected ") + 1; - yysize += yystrlen (yytname[yytype]); + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { @@ -1777,16 +1784,13 @@ yyerrlab: if (yycount < 5) { - yycount = 0; - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); - yyx++) + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - const char *yyq = ! yycount ? ", expecting " : " or "; - yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yyprefix); yyp = yystpcpy (yyp, yytname[yyx]); - yycount++; + yyprefix = " or "; } } yyerror (yymsg); @@ -1804,38 +1808,57 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an + /* If just tried and failed to reuse look-ahead token after an error, discard it. */ - /* Return failure if at end of input. */ - if (yychar == YYEOF) + if (yychar <= YYEOF) { - /* Pop the error token. */ - YYPOPSTACK; - /* Pop the rest of the stack. */ - while (yyss < yyssp) - { - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[*yyssp], yyvsp); - YYPOPSTACK; - } - YYABORT; + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + yydestruct ("Error: popping", + yystos[*yyssp], yyvsp); + } } - - YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); - yydestruct (yytoken, &yylval); - yychar = YYEMPTY; - + else + { + yydestruct ("Error: discarding", yytoken, &yylval); + yychar = YYEMPTY; + } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; -/*----------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action. | -`----------------------------------------------------*/ +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + +yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ @@ -1857,22 +1880,22 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[yystate], yyvsp); - yyvsp--; - yystate = *--yyssp; + yydestruct ("Error: popping", yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; - YYDPRINTF ((stderr, "Shifting error token, ")); - *++yyvsp = yylval; + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + yystate = yyn; goto yynewstate; @@ -1888,6 +1911,9 @@ yyacceptlab: | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: + yydestruct ("Error: discarding lookahead", + yytoken, &yylval); + yychar = YYEMPTY; yyresult = 1; goto yyreturn; @@ -1923,18 +1949,18 @@ void conf_parse(const char *name) sym_init(); menu_init(); modules_sym = sym_lookup("MODULES", 0); - rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL); + rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); - //zconfdebug = 1; +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif zconfparse(); if (zconfnerrs) exit(1); menu_finalize(&rootmenu); for_all_symbols(i, sym) { - if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym)) - printf("\n"); - else - sym->flags |= SYMBOL_CHECK_DONE; + sym_check_deps(sym); } sym_change_count = 1; @@ -1949,20 +1975,25 @@ const char *zconf_tokenname(int token) case T_ENDCHOICE: return "endchoice"; case T_IF: return "if"; case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; } return ""; } -static bool zconf_endtoken(int token, int starttoken, int endtoken) +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) { - if (token != endtoken) { - zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken)); + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); zconfnerrs++; return false; } if (current_menu->file != current_file) { - zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken)); - zconfprint("location of the '%s'", zconf_tokenname(starttoken)); + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); zconfnerrs++; return false; } @@ -1973,7 +2004,19 @@ static void zconfprint(const char *err, ...) { va_list ap; - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1); + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); va_start(ap, err); vfprintf(stderr, err, ap); va_end(ap); @@ -1982,7 +2025,9 @@ static void zconfprint(const char *err, ...) static void zconferror(const char *err) { +#if YYDEBUG fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif } void print_quoted_string(FILE *out, const char *str) @@ -2119,6 +2164,7 @@ void zconfdump(FILE *out) } #include "lex.zconf.c" +#include "util.c" #include "confdata.c" #include "expr.c" #include "symbol.c" diff --git a/scripts/kconfig/zconf.tab.o b/scripts/kconfig/zconf.tab.o index 3d1d070f0..e14d89825 100644 Binary files a/scripts/kconfig/zconf.tab.o and b/scripts/kconfig/zconf.tab.o differ diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 7f393a024..0691aca51 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1745,6 +1745,8 @@ static int snd_pcm_oss_open_file(struct file *file, for (idx = 0; idx < 2; idx++) { if (setup[idx].disable) continue; + if (! pcm->streams[idx].substream_count) + continue; /* no matching substream */ if (idx == SNDRV_PCM_STREAM_PLAYBACK) { if (! (f_mode & FMODE_WRITE)) continue; diff --git a/sound/core/timer.c b/sound/core/timer.c index cdeeb639b..4585600ba 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -628,8 +628,9 @@ static void snd_timer_tasklet(unsigned long arg) struct snd_timer_instance *ti; struct list_head *p; unsigned long resolution, ticks; + unsigned long flags; - spin_lock(&timer->lock); + spin_lock_irqsave(&timer->lock, flags); /* now process all callbacks */ while (!list_empty(&timer->sack_list_head)) { p = timer->sack_list_head.next; /* get first item */ @@ -649,7 +650,7 @@ static void snd_timer_tasklet(unsigned long arg) spin_lock(&timer->lock); ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; } - spin_unlock(&timer->lock); + spin_unlock_irqrestore(&timer->lock, flags); } /* diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile index d2afaea30..2fb4f7409 100644 --- a/sound/isa/cs423x/Makefile +++ b/sound/isa/cs423x/Makefile @@ -11,6 +11,7 @@ snd-cs4236-objs := cs4236.o # Toplevel Module Dependency obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o +obj-$(CONFIG_SND_MIRO) += snd-cs4231-lib.o obj-$(CONFIG_SND_OPL3SA2) += snd-cs4231-lib.o obj-$(CONFIG_SND_CS4231) += snd-cs4231.o snd-cs4231-lib.o obj-$(CONFIG_SND_CS4232) += snd-cs4232.o snd-cs4231-lib.o diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index a2081803a..8f34986dd 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -318,17 +318,19 @@ config SND_FM801 To compile this driver as a module, choose M here: the module will be called snd-fm801. -config SND_FM801_TEA575X - tristate "ForteMedia FM801 + TEA5757 tuner" +config SND_FM801_TEA575X_BOOL + bool "ForteMedia FM801 + TEA5757 tuner" depends on SND_FM801 - select VIDEO_DEV help Say Y here to include support for soundcards based on the ForteMedia FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media - Forte SF256-PCS-02). + Forte SF256-PCS-02) into the snd-fm801 driver. - To compile this driver as a module, choose M here: the module - will be called snd-fm801-tea575x. +config SND_FM801_TEA575X + tristate + depends on SND_FM801_TEA575X_BOOL + default SND_FM801 + select VIDEO_DEV config SND_HDA_INTEL tristate "Intel HD Audio" diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 873f486b0..118dcc71e 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -47,7 +47,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) struct snd_rawmidi *rmidi; int temp, mode; struct snd_mpu401 *mpu; - int port; + unsigned long port; #ifdef VORTEX_MPU401_LEGACY /* EnableHardCodedMPU401Port() */ diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index d72fc28c5..09a2885ca 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -35,7 +35,7 @@ #include -#if (defined(CONFIG_SND_FM801_TEA575X) || defined(CONFIG_SND_FM801_TEA575X_MODULE)) && (defined(CONFIG_VIDEO_DEV) || defined(CONFIG_VIDEO_DEV_MODULE)) +#ifdef CONFIG_SND_FM801_TEA575X_BOOL #include #define TEA575X_RADIO 1 #endif diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e821d65af..9dd541df6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1393,10 +1393,10 @@ static int azx_free(struct azx *chip) msleep(1); } - if (chip->remap_addr) - iounmap(chip->remap_addr); if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); + if (chip->remap_addr) + iounmap(chip->remap_addr); if (chip->bdl.area) snd_dma_free_pages(&chip->bdl); diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 40f000ba1..d7343dc82 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1488,6 +1488,9 @@ enum { /* reivision id to check workarounds */ #define AD1988A_REV2 0x100200 +#define is_rev2(codec) \ + ((codec)->vendor_id == 0x11d41988 && \ + (codec)->revision_id == AD1988A_REV2) /* * mixers @@ -1579,6 +1582,7 @@ static struct snd_kcontrol_new ad1988_6stack_mixers1[] = { HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), + { } /* end */ }; static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { @@ -1587,6 +1591,7 @@ static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), + { } /* end */ }; static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { @@ -1625,6 +1630,7 @@ static struct snd_kcontrol_new ad1988_3stack_mixers1[] = { HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), + { } /* end */ }; static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { @@ -1632,6 +1638,7 @@ static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT), + { } /* end */ }; static struct snd_kcontrol_new ad1988_3stack_mixers2[] = { @@ -2138,7 +2145,7 @@ static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx) /* A B C D E F G H */ 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06 }; - if (codec->revision_id == AD1988A_REV2) + if (is_rev2(codec)) return idx_to_dac_rev2[idx]; else return idx_to_dac[idx]; @@ -2507,7 +2514,7 @@ static int patch_ad1988(struct hda_codec *codec) mutex_init(&spec->amp_mutex); codec->spec = spec; - if (codec->revision_id == AD1988A_REV2) + if (is_rev2(codec)) snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl); @@ -2533,13 +2540,13 @@ static int patch_ad1988(struct hda_codec *codec) case AD1988_6STACK_DIG: spec->multiout.max_channels = 8; spec->multiout.num_dacs = 4; - if (codec->revision_id == AD1988A_REV2) + if (is_rev2(codec)) spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2; else spec->multiout.dac_nids = ad1988_6stack_dac_nids; spec->input_mux = &ad1988_6stack_capture_source; spec->num_mixers = 2; - if (codec->revision_id == AD1988A_REV2) + if (is_rev2(codec)) spec->mixers[0] = ad1988_6stack_mixers1_rev2; else spec->mixers[0] = ad1988_6stack_mixers1; @@ -2555,7 +2562,7 @@ static int patch_ad1988(struct hda_codec *codec) case AD1988_3STACK_DIG: spec->multiout.max_channels = 6; spec->multiout.num_dacs = 3; - if (codec->revision_id == AD1988A_REV2) + if (is_rev2(codec)) spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2; else spec->multiout.dac_nids = ad1988_3stack_dac_nids; @@ -2563,7 +2570,7 @@ static int patch_ad1988(struct hda_codec *codec) spec->channel_mode = ad1988_3stack_modes; spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes); spec->num_mixers = 2; - if (codec->revision_id == AD1988A_REV2) + if (is_rev2(codec)) spec->mixers[0] = ad1988_3stack_mixers1_rev2; else spec->mixers[0] = ad1988_3stack_mixers1; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f0e9a9c90..94cf292d9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3827,7 +3827,7 @@ static struct hda_board_config alc260_cfg_tbl[] = { { .modelname = "hp", .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP }, + { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP }, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8c440fb98..d8622951c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1262,13 +1262,13 @@ static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, int change; change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, - 0x80, valp[0] & 0x80); + 0x80, (valp[0] ? 0 : 0x80)); change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, - 0x80, valp[1] & 0x80); + 0x80, (valp[1] ? 0 : 0x80)); snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, - 0x80, valp[0] & 0x80); + 0x80, (valp[0] ? 0 : 0x80)); snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, - 0x80, valp[1] & 0x80); + 0x80, (valp[1] ? 0 : 0x80)); return change; } diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 61f82f0d5..10586e48a 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -389,7 +389,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," /* use hotplug firmeare loader? */ #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) -#ifndef HDSP_USE_HWDEP_LOADER +#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP) #define HDSP_FW_LOADER #endif #endif @@ -3169,9 +3169,10 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) char *clock_source; int x; - if (hdsp_check_for_iobox (hdsp)) + if (hdsp_check_for_iobox (hdsp)) { snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); return; + } if (hdsp_check_for_firmware(hdsp, 0)) { if (hdsp->state & HDSP_FirmwareCached) {