From 4e76c8a9fa413ccc09d3f7f664183dcce3555d57 Mon Sep 17 00:00:00 2001 From: Marc Fiuczynski Date: Thu, 19 Oct 2006 02:13:07 +0000 Subject: [PATCH] Merge to Fedora kernel-2.6.17-1.2187_FC5 patched with stable patch-2.6.17.13-vs2.0.2.1.diff --- .config | 2703 ++++++++++----- .config.old | 1609 ++++++--- Documentation/networking/netdevices.txt | 8 +- MAINTAINERS | 8 + arch/i386/Kconfig | 95 +- arch/i386/Kconfig.cpu | 2 +- arch/i386/Kconfig.debug | 1 + arch/i386/Makefile | 24 + arch/i386/kernel/Makefile | 22 +- arch/i386/kernel/acpi/Makefile | 4 + arch/i386/kernel/asm-offsets.c | 9 +- arch/i386/kernel/cpu/Makefile | 5 + arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 1 - arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 2 +- arch/i386/kernel/cpu/mtrr/Makefile | 7 + arch/i386/kernel/entry.S | 10 +- arch/i386/kernel/irq.c | 4 +- arch/i386/kernel/reboot.c | 8 - arch/i386/kernel/sysenter.c | 32 +- arch/i386/kernel/traps.c | 9 +- arch/i386/kernel/vm86.c | 12 + arch/i386/mm/Makefile | 8 + arch/i386/mm/pageattr.c | 2 +- arch/i386/mm/pgtable.c | 12 + arch/i386/oprofile/Makefile | 4 + arch/i386/pci/Makefile | 9 + arch/i386/pci/mmconfig.c | 9 +- arch/i386/power/Makefile | 4 +- arch/ia64/Kconfig | 3 + arch/ia64/kernel/sys_ia64.c | 28 +- arch/ia64/sn/kernel/xpc_channel.c | 4 +- arch/ia64/sn/kernel/xpc_main.c | 28 +- arch/ia64/sn/kernel/xpc_partition.c | 24 +- arch/powerpc/Kconfig | 3 + arch/powerpc/kernel/cpu_setup_power4.S | 2 + arch/powerpc/kernel/crash.c | 13 + arch/powerpc/platforms/pseries/xics.c | 25 +- arch/sparc/kernel/sys_sparc.c | 27 +- arch/sparc64/kernel/sys_sparc.c | 36 +- arch/sparc64/mm/generic.c | 2 + arch/um/kernel/physmem.c | 4 +- arch/x86_64/Kconfig | 64 +- arch/x86_64/Makefile | 20 + arch/x86_64/ia32/Makefile | 20 +- arch/x86_64/ia32/vsyscall-sigreturn.S | 2 +- arch/x86_64/kernel/Makefile | 19 +- arch/x86_64/kernel/acpi/Makefile | 1 + arch/x86_64/kernel/asm-offsets.c | 2 + arch/x86_64/kernel/entry.S | 2 +- arch/x86_64/kernel/init_task.c | 3 + arch/x86_64/kernel/irq.c | 4 +- arch/x86_64/kernel/pmtimer.c | 2 + arch/x86_64/kernel/setup.c | 2 +- arch/x86_64/kernel/setup64.c | 23 +- arch/x86_64/kernel/smp.c | 4 +- arch/x86_64/mm/Makefile | 10 + arch/x86_64/oprofile/Makefile | 5 +- arch/x86_64/pci/Makefile | 12 + arch/x86_64/pci/mmconfig.c | 13 +- block/elevator.c | 3 +- block/ll_rw_blk.c | 2 +- configs/kernel-2.6.17-i586.config | 28 +- configs/kernel-2.6.17-i686-smp.config | 20 +- configs/kernel-2.6.17-i686.config | 20 +- drivers/Makefile | 1 + drivers/acpi/Kconfig | 3 +- drivers/acpi/namespace/nsxfeval.c | 5 +- drivers/block/aoe/aoenet.c | 3 +- drivers/cdrom/cdrom.c | 2 +- drivers/char/mem.c | 38 +- drivers/char/tpm/tpm_tis.c | 1 + drivers/char/tty_io.c | 34 +- drivers/firmware/Kconfig | 2 +- drivers/i2c/busses/scx200_acb.c | 20 +- drivers/i2c/i2c-core.c | 4 +- drivers/ide/ide-lib.c | 8 +- drivers/ide/pci/via82cxxx.c | 3 +- drivers/ieee1394/ohci1394.c | 4 +- drivers/ieee1394/sbp2.c | 3 + drivers/infiniband/hw/mthca/mthca_reset.c | 59 + .../infiniband/ulp/ipoib/ipoib_multicast.c | 6 +- drivers/md/dm-exception-store.c | 65 +- drivers/md/dm-ioctl.c | 34 +- drivers/md/dm-mpath.c | 3 +- drivers/md/dm-raid1.c | 67 +- drivers/md/dm-snap.c | 6 +- drivers/md/dm.c | 101 +- drivers/md/raid1.c | 4 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 10 + drivers/media/dvb/bt8xx/dvb-bt8xx.h | 1 + drivers/media/dvb/dvb-core/dvb_frontend.c | 14 +- drivers/media/dvb/dvb-core/dvb_net.c | 4 +- drivers/media/dvb/frontends/dvb-pll.c | 10 +- drivers/media/dvb/ttpci/budget-av.c | 24 +- drivers/media/dvb/ttpci/budget.c | 6 - drivers/media/video/Kconfig | 6 +- drivers/media/video/stradis.c | 1 - drivers/net/8139cp.c | 2 +- drivers/net/bnx2.c | 8 +- drivers/net/bonding/bond_main.c | 9 +- drivers/net/chelsio/sge.c | 4 +- drivers/net/e1000/e1000_hw.c | 1 + drivers/net/e1000/e1000_hw.h | 1 + drivers/net/e1000/e1000_main.c | 11 +- drivers/net/forcedeth.c | 26 +- drivers/net/hamradio/6pack.c | 8 +- drivers/net/hamradio/mkiss.c | 8 +- drivers/net/ifb.c | 10 +- drivers/net/irda/vlsi_ir.c | 2 +- drivers/net/ixgb/ixgb_main.c | 4 +- drivers/net/loopback.c | 4 +- drivers/net/mv643xx_eth.c | 2 +- drivers/net/natsemi.c | 4 +- drivers/net/r8169.c | 2 +- drivers/net/s2io.c | 16 +- drivers/net/sky2.c | 114 +- drivers/net/sky2.h | 17 +- drivers/net/tg3.c | 16 +- drivers/net/tg3.h | 1 + drivers/net/tulip/winbond-840.c | 9 +- drivers/net/typhoon.c | 6 +- drivers/net/via-velocity.c | 16 +- drivers/net/wireless/orinoco.c | 4 +- drivers/net/wireless/spectrum_cs.c | 2 +- drivers/oprofile/buffer_sync.c | 66 +- drivers/oprofile/cpu_buffer.c | 51 +- drivers/oprofile/cpu_buffer.h | 9 +- drivers/oprofile/event_buffer.h | 7 +- drivers/oprofile/oprof.c | 34 +- drivers/oprofile/oprof.h | 7 +- drivers/oprofile/oprofile_files.c | 205 +- drivers/pci/Kconfig | 1 + drivers/pci/quirks.c | 2 +- drivers/pnp/resource.c | 3 +- drivers/s390/net/qeth_eddp.c | 12 +- drivers/s390/net/qeth_main.c | 8 +- drivers/s390/net/qeth_tso.h | 2 +- drivers/scsi/Makefile | 2 +- drivers/scsi/iscsi_tcp.c | 3006 +++++++++++------ drivers/scsi/iscsi_tcp.h | 190 +- drivers/scsi/scsi_ioctl.c | 5 +- drivers/scsi/scsi_transport_iscsi.c | 705 ++-- drivers/serial/8250.c | 42 +- drivers/serial/Kconfig | 2 + drivers/serial/serial_core.c | 12 +- drivers/usb/host/uhci-q.c | 8 +- drivers/usb/serial/ftdi_sio.c | 84 +- drivers/usb/storage/unusual_devs.h | 12 +- drivers/usb/storage/usb.c | 18 +- drivers/video/Kconfig | 2 +- drivers/video/console/softcursor.c | 6 +- drivers/xen/Makefile | 16 +- drivers/xen/balloon/balloon.c | 749 ++-- drivers/xen/blkback/Makefile | 3 +- drivers/xen/blkback/blkback.c | 1079 +++--- drivers/xen/blkback/common.h | 176 +- drivers/xen/blkback/interface.c | 352 +- drivers/xen/blkback/vbd.c | 338 +- drivers/xen/blkfront/Makefile | 4 +- drivers/xen/blkfront/blkfront.c | 1951 ++++------- drivers/xen/blkfront/block.h | 119 +- drivers/xen/blkfront/vbd.c | 635 ++-- drivers/xen/blktap/Makefile | 4 +- drivers/xen/blktap/blktap.c | 1473 +++++++- drivers/xen/console/Makefile | 2 +- drivers/xen/console/console.c | 1009 +++--- drivers/xen/evtchn/evtchn.c | 654 ++-- drivers/xen/netback/Makefile | 5 +- drivers/xen/netback/common.h | 175 +- drivers/xen/netback/interface.c | 617 ++-- drivers/xen/netback/netback.c | 1806 ++++++---- drivers/xen/netfront/Makefile | 4 +- drivers/xen/netfront/netfront.c | 2687 +++++++++------ drivers/xen/privcmd/Makefile | 2 +- drivers/xen/privcmd/privcmd.c | 394 ++- fs/Kconfig | 1 + fs/befs/linuxvfs.c | 11 +- fs/binfmt_elf.c | 15 +- fs/buffer.c | 7 +- fs/ext2/super.c | 41 + fs/ext3/inode.c | 19 +- fs/ext3/namei.c | 15 +- fs/ext3/super.c | 40 + fs/file.c | 4 +- fs/locks.c | 6 +- fs/namei.c | 8 +- fs/proc/base.c | 35 +- fs/splice.c | 230 +- fs/udf/super.c | 2 +- fs/udf/truncate.c | 64 +- fs/xfs/xfs_dir2_node.c | 2 +- include/asm-generic/mman.h | 6 + include/asm-i386/apic.h | 2 + include/asm-i386/desc.h | 2 +- include/asm-i386/fixmap.h | 4 +- include/asm-i386/mach-default/mach_traps.h | 12 + include/asm-i386/page.h | 2 +- include/asm-i386/pgtable-2level-defs.h | 2 + include/asm-i386/pgtable-3level-defs.h | 2 + include/asm-i386/spinlock.h | 2 +- include/asm-ia64/mman.h | 8 + include/asm-ia64/sn/xp.h | 22 +- include/asm-ia64/sn/xpc.h | 4 +- include/asm-s390/futex.h | 5 +- include/asm-sparc/mman.h | 6 + include/asm-sparc64/mman.h | 6 + include/asm-sparc64/sfp-machine.h | 2 +- include/asm-um/page.h | 2 +- include/asm-x86_64/apic.h | 2 + include/asm-x86_64/hw_irq.h | 2 +- include/asm-x86_64/ipi.h | 2 + include/asm-x86_64/pgtable.h | 2 +- include/linux/autoconf.h | 2703 ++++++++++----- include/linux/ethtool.h | 2 + include/linux/ext3_fs.h | 9 + include/linux/gfp.h | 6 +- include/linux/highmem.h | 6 + include/linux/idr.h | 1 + include/linux/interrupt.h | 6 + include/linux/mm.h | 10 + include/linux/netdevice.h | 74 +- include/linux/netfilter_bridge.h | 16 +- include/linux/oprofile.h | 11 + include/linux/pci_ids.h | 5 +- include/linux/pfn.h | 2 +- include/linux/skbuff.h | 97 +- include/linux/tty.h | 2 - include/net/pkt_sched.h | 7 +- include/net/protocol.h | 3 + include/net/sctp/sctp.h | 13 - include/net/sctp/sm.h | 3 +- include/net/sock.h | 4 + include/net/tcp.h | 7 +- include/scsi/iscsi_if.h | 128 +- include/scsi/iscsi_proto.h | 2 + include/scsi/scsi_transport_iscsi.h | 119 +- include/sound/initval.h | 3 +- kernel/Kconfig.preempt | 1 + kernel/fork.c | 3 + kernel/futex.c | 1 + kernel/irq/manage.c | 26 +- kernel/irq/spurious.c | 3 +- kernel/sched.c | 25 +- kernel/stop_machine.c | 1 - kernel/timer.c | 60 +- lib/Makefile | 3 + lib/idr.c | 43 + lib/spinlock_debug.c | 10 +- lib/ts_bm.c | 11 +- mm/Kconfig | 8 +- mm/filemap.c | 34 +- mm/filemap.h | 4 +- mm/highmem.c | 11 + mm/memory.c | 119 +- mm/mmap.c | 17 +- mm/page_alloc.c | 11 +- mm/pdflush.c | 15 +- mm/swapfile.c | 3 +- net/8021q/vlan.c | 8 +- net/atm/clip.c | 8 +- net/bridge/br_device.c | 8 +- net/bridge/br_forward.c | 12 +- net/bridge/br_if.c | 23 +- net/bridge/br_netfilter.c | 7 +- net/bridge/netfilter/ebt_ulog.c | 3 + net/core/dev.c | 289 +- net/core/dev_mcast.c | 28 +- net/core/dst.c | 3 +- net/core/ethtool.c | 39 +- net/core/netpoll.c | 9 +- net/core/pktgen.c | 12 +- net/core/rtnetlink.c | 15 +- net/core/skbuff.c | 285 +- net/decnet/dn_nsp_in.c | 3 +- net/decnet/dn_route.c | 3 +- net/decnet/dn_rules.c | 3 +- net/ieee80211/Kconfig | 1 + net/ipv4/af_inet.c | 87 + net/ipv4/fib_rules.c | 4 +- net/ipv4/fib_semantics.c | 12 +- net/ipv4/ip_output.c | 22 +- net/ipv4/ipcomp.c | 11 +- net/ipv4/netfilter/arp_tables.c | 3 +- net/ipv4/netfilter/ip_conntrack_helper_h323.c | 2 +- net/ipv4/netfilter/ip_nat_proto_tcp.c | 7 +- net/ipv4/netfilter/ip_nat_proto_udp.c | 10 +- net/ipv4/netfilter/ip_tables.c | 3 +- net/ipv4/netfilter/ipt_ULOG.c | 5 + net/ipv4/route.c | 2 +- net/ipv4/tcp.c | 86 +- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_ipv4.c | 18 + net/ipv4/tcp_output.c | 48 +- net/ipv4/xfrm4_output.c | 60 +- net/ipv6/addrconf.c | 2 + net/ipv6/exthdrs.c | 29 +- net/ipv6/ip6_output.c | 9 +- net/ipv6/ipcomp6.c | 11 +- net/ipv6/xfrm6_output.c | 39 +- net/ipx/af_ipx.c | 3 +- net/netfilter/nfnetlink_log.c | 3 + net/sched/act_api.c | 18 +- net/sched/sch_generic.c | 66 +- net/sched/sch_teql.c | 9 +- net/sctp/sm_make_chunk.c | 30 +- net/sctp/sm_statefuns.c | 20 +- net/sctp/socket.c | 20 +- net/sunrpc/cache.c | 6 +- scripts/basic/.docproc.cmd | 17 +- scripts/basic/.fixdep.cmd | 16 +- scripts/basic/.split-include.cmd | 12 +- scripts/basic/docproc | Bin 19832 -> 13404 bytes scripts/basic/fixdep | Bin 15691 -> 8881 bytes scripts/basic/split-include | Bin 14592 -> 7891 bytes scripts/kconfig/.conf.cmd | 2 +- scripts/kconfig/.conf.o.cmd | 32 +- scripts/kconfig/.kxgettext.o.cmd | 10 +- scripts/kconfig/.mconf.o.cmd | 24 +- scripts/kconfig/.zconf.tab.o.cmd | 31 +- scripts/kconfig/conf | Bin 20591 -> 67464 bytes scripts/kconfig/conf.o | Bin 10348 -> 11136 bytes scripts/kconfig/kxgettext.o | Bin 2324 -> 2416 bytes scripts/kconfig/lex.zconf.c | 1805 ++-------- scripts/kconfig/mconf.o | Bin 20532 -> 29292 bytes scripts/kconfig/zconf.tab.c | 1182 +++---- scripts/kconfig/zconf.tab.o | Bin 95696 -> 66344 bytes sound/core/oss/pcm_oss.c | 2 + sound/core/timer.c | 5 +- sound/isa/cs423x/Makefile | 1 + sound/pci/Kconfig | 14 +- sound/pci/au88x0/au88x0_mpu401.c | 2 +- sound/pci/fm801.c | 2 +- sound/pci/hda/hda_intel.c | 4 +- sound/pci/hda/patch_analog.c | 19 +- sound/pci/hda/patch_realtek.c | 2 +- sound/pci/hda/patch_sigmatel.c | 8 +- sound/pci/rme9652/hdsp.c | 5 +- 337 files changed, 19517 insertions(+), 14046 deletions(-) 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 51640ad93660a5e29ce19452befa76d58d827f84..939288420f5423503829a9e2f93da5b135ade1f3 100755 GIT binary patch literal 13404 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 D2rT18 literal 19832 zcmeHvdwf&Jnf6FJ5^@l>z(Am(L;;bK7Rxrb040gRHpGp=@&!YhW`!)tmOz$NUASyQ zVrpn2RBv38ZPRYrg{GU*ZMvb|Cgqppqb8=I?QXj?y>63c+1>Q3sL6&l38785-shP) zM?QA5rI-D_-~Pd|=gd6wzVpsI@4PcQXXc!9cVqK9i^U?0!zyfoD0PqKT#ERC6^gP{ zc*G>JP+TMC3J0=CTiOR6gfmDp*by`Y8^Ux5nZ8$ZGE@RHkVe@I@<3TZ8Pg#Pf#ro; zr+bh-1UiBr1^iQlte12vNG{M_pfP+6n1On+4u*v&vk-MNcz_uUTI)};VZh%yjPlj- zSXXsCTosQca=Uz)q;Ih*i>jsW>o;zaWvK@P^`44w6#~?hM;Xp+vvJHuqCy8(AfAO# zjxYn^N(2|e+Yo-&LAx3U+rqkeP;VYi6-gZ@>FH^RC+lhI2s4YB2yBbAH)8V<1#o{* zb2cDm*@Xxm;A5~S@eK$yz?4B8LZ}1YsN>~`{lG8in00Rj9?@|%;uP?Gx;)x!>tW5w z_DqFlI}nFWxDmJy{KJS@A8k4ae5a1*AwC4WM3;99@KNA-IzA3O1bhU>V);iAP6PiG zF>xEh8Q>P3ek1UC;CJctBw~TF5Y*+p7tjs7MyDS{>;XQZ{x*sJ4D zAl`S-Xm7bF0Q*7r=<@dfZw20pnEFwUad?=3Z-(fT%S9@e4Ml@#u`?LUrea}{$%d1; ztmy8EWHTZaNvD%((Ho4%lOfUF9nWQ=qC1t2C9>V3I}?d)2Y(v>A{|jYfdEiAmlEB{ zv?PXlkq*U^nFvKgo(Kd&+1;r~perDS?o7wB5fRxHL#4@7Bq0J#Ef5lpB?7rjBn);c zi=1FO8|V$j65x%5c0g)65&^ZRH<{3>0kOWhX>EOAv2RH!Ra;8cu;JEA{@HX6&R|wK z+Bsg;d`5rgQ5lP2h-%`Wk!IdhiEZNFb?lbdDqaTW(F|X7U|`Zm?HFM6O*;nnYnXQ? zq0cTdhVT5EF$XBFiV+=|+V@v?k8BfMMz!-yn4r6HMVT_5v%NP^J zLdH;Z5n~MC8pd#prHnBcRxrk(Udf|5^TD`(HZm?`Vsj{xB$gIJI_0Q}=1k z;!UXkwZTF3ReKQy#BF{{`gh0+u6hEAzgFy#AAmh6l3OivDx64sWIW;ursux$fe}5$B)jzc`v*1I0R9 zw~2uUuiM{N{I+5!GV;t@rB2iSntnGn>%YqA;eXvVxg6<>{)u8MQWcPcmlcz z*^q_)f|TPgR{dHUG5-sgZp!-pVORgNu9dIc`Ome_!5sP1(CGGIRdC?xcd$IvQ z4~-}9Jvj$iQcEi(gMeHyxR;7<6)rYNt4HW$D0 zrY@;s-xtxg&d%tQD7CrxWtE?QmZcs8rML-l3hoi>;JO2ID~=Ce(AGM0ul2nd$i7ls zrATGUOgg<`t;LgjweQV^xr4>oU|5I3mUR`!9Tz0!^`eH%{Hq1$h^78OWySGlE@*2g z@mG-etWC7Gb{0Ckv)YQESI$w=cuGm*{Tpe9bFNLrTUDOP7VYiPf0PaRk6)?oWkdE~ zj{J1J)jo$FsC}LuHAVU*oOb0uz{pPc zffuoM_l#rrLf)D|c6(uA|B%b_v!>hylo-&y=Z5wC#cNG^?E4t9PH7K*7BxSGUm9_$ zPJ0Py>D2p&?z#cvjvkvoA?0b_+UE*U=gOb$nN`@O4Wd#luYIzrsRpl$vkhW5ErWPEt#Y7I>>J9xtFX`Omt0Tt0$t=Ap5_dUi4IDf zg?4*SHiIk&!o9=A&#+-9MrLDJKCAgkvezBZeD@CT8_Is6;`nz8mJ1DjIO&UMi3?-t z-%dd$H6PG?>#2=V&-#&5rtz%CqYJ|)|I?AH^B4LrHdO5UI(SR=acv%*ar5Unue<$F z+Y45|KHgd`N_XU_dKE?bR(r3>eXHVlgV!>U^;-KcHs)W?`Vrmr+5U^`D)xN}JpC7& za-SQSR{SoCQfr~Ko`i9>@A+I2MtIgCHjU1xLyaRJ%3mmc?h=g6V3b!5YP=TjxCDO# z`FZ7_^WXB;{LrFU1JcBS-qzL$?N(682%P~xkLu^^)eG#k()2ZGjJNzxFy6q1Yk>Ye zPFuzPPr@wXYJ5|HMTc?I7kV+I61}}!sBlA|E~*s&gW0O`bfq8+aVdh7mcn$ zozow^613uvp*3cTQ+D=n-2wQiotAgY6iusAG@44WCUEc)gBJYVRH=fV`V08M?LgV>$D}R%I9lzt!n&bSd zi0XOuI7La*1wADNT|9Box_@XOHJYm|wt=lAKwdwLPXBWL{Kox5xeLW*CSvIth}WiV zPkk3xhKG6LWtppgL>oO_upym$ZOd)950l5xpn!WBf3Xv0yA>C%RBQZ!Sxw%pjn5rJ zn=-+k$SO}b8A_#-ADGW;49U(;bUP=x@L4XiDHV*%QlnaGM+Ubf=TOvY0R1 zn~M89ExD{t&O{PfPd4dMH_>BKQQs;SOJq@{XJ<5$@bp9yk#sN{OZ0fQN79K%oZ97j zApn`l#8_GCrF30o6pDD_u}s#J?3P+ktL{iTk_bg0JC=>c5_+TLJvi@{J(*BCmda+T zRaI4}N|Y_gh_qwwBKd+%e2cDxNL#T7PxGI z%NDq7fy)-SY=O%bxNL#{#TGb&n>nseF>q<9xLFd zoV*=)0|DDuaxaa0**thpSA;y?1Rq7+9=Rc^2Z4f$Ka=d`o5mVfKdw=%^6bUgDheh3ZMt9oC-_x8ikW4sB98Mz=+Au!6E?NU z7L`m)amzs|cMui&eASuV8Qel=s$)x5EU%8lyQ}5yx367PN0Ysg>YlFZbgH*{?WU&Y zhUy+}k5^&K+qa}Tl*tJ=iDyl_XR)t#sc$8`!gsx}^gRd_ta1oxmiMDBHjKfCnx9A8 z;~0$=>puZmzgGjgZ3%{-HpzMnt+LHq%bZW)WN}(=V$S>y=G=#qb&~Z_l(KnQ%KBas z7q9}GPYGC#;ci>l&zw)=WN}#epo#4|inM-=$#)(i@nw{>+N~`pWqTK;TR+c|i~bLi z8Xh+gn%(+0lwKt(`VDlpE&dTpjw07-x1OOEOU^OpItambdMnxAO&)8IVpo%BeS^98 z%48jL^HSc&SlI!YoJ@uS+hCo+T0SIs+nF4Y3|-{?3z@8BrT6iv4x0vH&~YY-gR;`= zDd@v&fc-DQ;j|red=tQSkjOe;h)I8g1nEvD@Qi_O^biXkyo+3)VYTBaXYNNO?@=Znl(~G2!1ghjdlPm0D^_TYGx?C>Wo@63xrdp1NG1oF z`>;%YgH=2tc_U1IPA0FX+(%_Yn^^2IsaXSak4nv!k@xRq?t7U0lFYq|$tR@T5PSd0 zC^D??W3i_`i#p3RuK8OxkoNSGGGmCUd=9yAo?p`lUy;RcrKD%r#w)HyaciT6dR_5e za9F!6%%40RX-#W)U0~dL7IIuSGucLhnB>Ko!ln6b!rlbz)H)nZ$kR5;O6Cj4cfhK( zzm7cXd`(yf&{(a5MeVzBa@prPx>3D-PA3}z{uSW2zn!uq|03|)=W_GL{#l&d_W6qc z8rg7zf1cuZ3hM_U#y)=^Sf~6FC(Utfc@-pz@=9o6DgQW|TFxI)Tlp`*s+Gr)Z!iB6 z(vEWeMoud4!P!~913YD7N;wK>juqwaKx`@hAu{m@%oQ-N%r!JlBXe_{(+|-@FZDyLcuNIoJ!6U&|tOWCdaoBJ93X;kAQX2?(DCBmWBIh2eZJj^e;emX|T|dUzI)9eq7-imVlQQQx z{)4nWuS6clJj&dsYVbN$#Ug*3+ph#pj;oQ`=E{E$K}M*-y>YHZDSI~K6X zpL$f9YPxh8$HU46W;rghS)cj1q2FF!c(al7+s>LUbxs zHB;_i@I?1S!(K*u8V7Zmb`i-kO*-IVc1*YoCN0w{aIWy;q$DuqCKE`q+vDVoER($N z#<_AmdEKOmsqB?0V3_V$>-bkPZljIp?%yQZevd?&<01A){GH&YyGy6)mD1tvY?LFR z`qzzGDSt)^1uSLSA*9PRdcxGRNPYlyIvt;PJdfD%cMEW4Rck5yF%DFYEGhgbxlxsv zbP)+U?M(ir2q|^te~7sV!oEWK`(}z;DSyU0A=AE!)A5yeLSxJ9kD!>v zZsX&N)5t9DMzD%mP*k(9X_vUh>B`0MRBde8iskCjT3+;2htk>DpKy7kRN<n&rhm zUWLS;pn_$pa66`2rde#xtDFm*l`xyIOtrWj({Q$xUsb-Kyb_nB)|r_2S51ERR2Ka&xIqxq^H~xjD@PZVtDix`8z|I-Y%Ik?gvnu zgjgt<*datL5zG2QP=rs`h9lj+C>zFSYcohet0!)?cs#epoIG0w(%BQmkR zzGY))plM@$%LadQV@D&B{!Ja=P=uCSkc5+E<%7wzF@(gjf$k8bK%mT_z;ry;yL_ox zWOH-l`ZdjghQ{{#wkCf^OB=XkFF`_gQe>jZbk>tgWMVxDZ1eJts08Hm+W|f;4f)}W zlp0Fru-VLqt!3ST9lKyHtHwHn}sT zOG$QjOWsT-_UFnVvau<{6;WFT`{|)XRAGS$b{16D`$spX(K)E3q;NJFNCbOngdB?Kf@5K+ zj4Iu@!QXLfsbfQY0zH;Uniw{=&k~bHSeFip3L;U_+&>+Q= zi5}#1XU5gMZc}q}pk-5saw$`XWRqZ~6Q-qTY4q+Kdz6jPopgI-w_dUC5XxNaYA|M^ zn3DogOh<7xz88%9%(%Da>a!;u{jLj^tZq;hrBOS6ZA*&syVHG!^Nw~4dlkg7;d zZyRQzE?raUYCA#J6)joBEPkw4yW_zgc&T0!@{tZDd%I#70!W$*jSVx?hzs;4!+K|D zrREqP*~l(^JO)&r8Xp{xQYmN)(NHm!)r~!FT)`8h&&a7&7SLU;J&M^*dRprK(hP42Aw<5G%YBJW}0lkaN z7J7d!lHM(c%OxguE+R<_=xs1++t9cH`IrLqeAC3RKEP2bm4K=%WFlN@qG1GPuQz*a z0`EpC)iXO`Cs|B4=f;l4wvCt%8{69CREQr!POFloM|UjQay^Y|^VMybUD-9Vyzpgq_hy4#h_h)GM~#&9n3V7(lG%uF&Dy4_Y_Lc8qCvdB;|uRjprDHJ z>W&Xr6}}yjbcWCHm_Y!vbRlr?*9`ztQZ~{TiQ<=obE{8blneI8 zLc$lyCeyf%39D#Zh;=4WyeorT3}`;}1ahP+*Aob0p!P(_EnzCx#SvV>^2g9%?dnQL zb{L%SCDtrU@r|V4_u#u@yd>cLi+tA*09T@=LtZWb%}2nEkmQr^1cKlJHV#}>$)gr$ zURF^a_d9L|-!Y^OI%9_G5pV@8`M3|l#8L3d3xA!5*Pk~b-~vwaao^-90QXCb14ZPq z9%t@(uwL$W96=?^kv8gOJ_GN{xJSY?_esuxp$=(ty?`QwfQ4>ZhWjiYFmRv6kjI#J zgK-3dkNYw!z;{&VWBUxg9MaSkw}x_koy!&6%P|f^ZVDL&pTJ%T3-IpPILOCv2ZF)J z3;7f}=Oxp#WwafSy$A*$uSYwuVe~dhQ75C`dvre9r4M|4;CsweuSc;9u6i?@d^LC$ zvj&T9h77V8X+FSCKK32oKNTLeCq~G_;QMQ&X%q6vcTqj+JyiAw5AxB@M-U8od}#8! z9+i)5c^L8@12Xtt0N)Fqx8{4o#K(7ZUIL#X1Ef;=DH9*}Ye$@}0uA$A#s5VI~GKSnU~x#tV9KvLAn zpuIeSZyES-zgRj9zF$t@tH<)|3WI2(@x47$wz$J5#1=Y*ei$_F5inh&=YI!@huPu! zK^ntU1lrCxc3^^-OM-qFNyesX#M3w6T~-W05Axd(*cbGDj!Cn;W=s%^Ce#a-w>&rx zlAzvtRPR75tZL@Grm$WE=P${xJc#p@!pe({{a2gxbT#iNItDEc&MykfNbc_{%vPxR zLSenbI4|I^>2D=-{40#51RNaa3Qv)k<5^)mNQ{HyR^bYX<@iL(CM~DNp`x=_gy48n z7?T1Hjw^-LF9pYs!d!uez9p=7vpF6VeWs)vC)>Cgko9wh9Xo6SFYcKR+qjvF{QUJA zJ8XhGo@0kiynPHHWy5>-=EEkgHbc-o(ie?PP5gY+m`9mMZ1|ypn+#^1&fgc~Ab-FB zh>0iCC(55lpIF~S{)zNU>GO#R`h0o<{+9{(ZKevS|3rQhS+?&F)o-FaZVhljglbsv z6b1LujDz*p0UQ2k!Q0&%fenAO;L7EFz=l6su;m*A=DVAeVS#`50?QXSC7vmE0}q+% zyAN30``_39SD^o}ByXBH0?g+=l>AEZIIuCkEcjZ%FtAx4ZZg;CWOKm2eOFft7qAxL;KV%mq8nMt=+J z2Yx}vPXinCnH&0lllViLvkZn}eLn)`t1GI$nc`=_d<)0W|L4G(-k(#gZt)vnzGJ*u z%6Ex!O!=!#<>vrzMg1ds{nfyHamJ9p2AFT#u%B4}Ex=p?1O&c9v;wD4o_@#ngn;=j z5Pvzyza5zKry*|-FyEaq@O{8_CixEnH<;@GG;kl}4@-GMJPteve5a1T25kI(u)co+ zu0j9S>Gi(|d-$F9#_GSOP z84AV%xYM>hlWy>332KsxuzPea~MCBG26fz9#`0G|Qf_!h+{Omq(< z9sxcN`n&YxdKK41^zozUgo2+Y^5jQae*`K+f4gwaB}G7cF1IN-Q6Gs0`*uu4>UKmcLV}J4dc*z>Pw`QuSUSssdywC z3Hxfn8cqg!;>j+ov&p53KrpupUm3yjLm-^%?cHsNZrs=~CfNY%+SY8qa*|GBHAZ?& zs$2(=QvXN;a{EGmBMU9XA`V|(n9b>o^1P4(CzO5;l` zb#=xEQffqw@5Bi#+y$aL^$)$6$@*7b#%1A?F5|HL9*j8$E86HEtl^}CySbu9WsR4@ zG9rVQ-Qtlkj3qHV5Lc1LZ;5szv*M<;liFSP<;i+OjJFlKK3(~UyHXFyMwuSR<^_VKF}Dw z2EL1ZoXD;ecDQsiW#l)00_tr=49k#61=E=bD!}H2VNnVA-5|3pIKEsdA9II5L@mLt zZ*EzO1?84?>)IPT0v&7CHa7<3H-yZ^rPIpK5RK(>W-wVsH}&`>`fm9Zqp>nI@`FZP xvd(dN-(FlFm9^P#~!KK35dA{9Y}8NaKgJee-}WLMQ0YO-NAVlZ9MXBQqX+wkBE3*k9UZZ*+PRS$0FUMiUya58o>6%*a* zOrqcG78xg+B+hzq)Rdk~ExvvxgNk0<)=T-J%BoGxg8`l5+` zkxD!Lu$PIs84*jSvX1Cjw{~Tly)b;$WUh(b<2o?yGk+B_?ipXqF$NgJOcy2+2=PjB z6nU1_N<2;ch(e?$#J~&$I%8ovCdqQ}b1?YrcDM<8z{$AsEW zj>&d2IVM(|9Kr6AVO`MjPJ$9E9-z+hE?yez@NX!v%BgD%k=190(iJK(m zh`2WsTM~0*Ty|)pR$`8jn--z9U?vsyx_lg$am~YW#g|yaM))dUKv;3&@-| ze6reQVfonbk=mnU`+>`g4xm==mAw`2J8-Zx8_m8L2yxbzK0r61Q(Ip2T{gDpN&LIF zejQr>2+8n~x-t0DiRdV757nMnl0OYM&hLIk1Yex~AXK^37Xud@W*$nB@}ftPE5%Uv zFmv#M-W6t3;m|?+RlL!1?9OL~j|8`k(bYVg`te6+9dc21)0WL>vicA$emLw{AS%AG2-heAWGGpcgGX&Eit z9TNshn=poGWET2m727HzrMVat>0#w`<#}~y*$Z71 zDSZ##RbE0Lq(kF@%Br@!#KT7}+Q#vLnHQ&1fe)cqxL@3lPCWp7di>a*JtwO%FA7hF zEVBDUA+XNPrJ2yW@dk|1xqFUKL3)OfglGpu#bl@s{&sHORBD79`wH0*BAC(3Ss7#($C-~*W!r3 zh8TnmUz?>y6ct3F?!dlFPrQQoQqKUxX%&*8P{j|5TLUdW8(1>&eOQLAW$UkBy|!kA zudZdtb<~V}hgsz8nvuU#I>TeAQgc@xs8G4A4K;EvY&_7$|gwg6Qt_l`XG(kK9vL^W5`zx`ESy zj$rQO&5? zwps>T&3!M_{Pk%43pLNZ05Rv^q5TLA)%^gPAKMsl*P!QWT9$tMKQj3Fom2YD52de+ z{v-l(uvc`JI#8A$mlLUG-`AiODYl1dBb$3GOaFnYctC5U&|8ZU=oOoLr}b7udPV60 z2=imZN37xZ%ieX6VN{k!N+Ar(4O^M-EPa(K&7o2|IBX0biErDX;<%}FA#pMAiJWYkVP)UGek&)f{2J&hS%wq6A8>$D(e^mKc=!?koF5Oc4 z_6O2~{P^C{nvn>?Hb2(z;fBsF=qhGlGwRFG-+H57p?=7w&O`C)(w!=lTi)H(h4{C; z>elUEu(hgY?=LV`t6Sb3n8?4^@=?vm&o(;$F;2{Vmj)bYebB_Mv3YkvcPV-8Yr3+DPdM*t%gGruI|r z`OuV4t@O7j+;Jlc58{cSXja6%kY-lE%r@nh@}YL(HiThmH_8ja{2%1nmH$a`OS$H` zj`HciilF!A#C&M9yjyeE#o(=0&B%q|`SMer*xk|*8|bnpj$IF=&oQr6LejZL03kv zF>EsE=28Vg_iyj{f-Zl0gKF7biqX(B<7H@2^C7?HWF$VIrFSdorz0_phIZ)wWT0fC zaRwdW`?E7rxTzYiZ@m6Wn;1oR1Os?0{}A#*Ti`GUqR!OV0li*@HiHS+H3AOl_?n=*hUNL8)D-j?glxRFZe!lgYs{9fIZjrKT8t?tBN+(}!l`0Gw2oolUDe7E;F9x}1MI5vOI zwN=7G3e^uJlJQtH6Sormv1BgpG{#c>-HD#YdD*brU~R|ur!uzG$|i1gQr-3Ves8e; zVwu%!r83q)Ce`0#IsNfOwBN~Que0V|HdrOlhCMH9EnQ~K%T`qx1AXd~pDzl$Mog(S znUR|Y(^xv1$vT$YO;ibVBdZO*jr!!|~9UWzVAPnzv zGUzhgf{Chm*`?^aw%Y(7&w{0s4pTXiwVb}Rw;SWYgoj=BbLRQ+!F>YvsKLE~Aosz? z^nPs39_$5xuO7zU0K5cDQ$GW7|B8i0?ybS(p0*iL$VGJ@hxR#Ta+3}sqb61~xlX?ezdfTD5{WJ6)@#%379{-GXAA=spnC;4Q zT6=OEONCfroI;_oXXJj)^@CWQ^s9A3VbwC%1BF!!oc9W=1~|VJ zR!_^kM=SM7Gv}+4b0t#mV})h0;QUjVGg8enh1CZH=aa&mnVA3j9a$;A9@KY(lJhG< z%>#uo8ITz73iBjf#kIm5Ih-9LE*0ie!P(&?=2wG?NAgO&!ZPj@R*}N^Qdpe|GmaFV zLnh-zVgJfOdlyN$`K!cTia%9Oneo)WSU$(N?*BCOUwN!*1;m@>I%GL-SyF+>;96?> zR{`y-fldD^aFV_XSRSBB{kd|T<>4A2>dz6|!1wvuy9M}JAO2+fcR;??*Zw`g{Eh*G zy_w=ZaPvGWa5M1`u-~7@fgi;>28Ot=7B4cR6Z>}zd7d3G(&*n$wanaGoCG%CV>9u* z-qmt*ZqIwDU%~&&P<{dIe_l@vbFXnFFxOE=_DtNGEYxyy&(W@NNY)o(3vjX!2tEK# zd%Qm|<6k@N&GG>7fxGc7sN2gE-xCP_SmOi0vw+uYd=Pk_9{-us=7_%sW{QFsjsF77 zb5-`A?Y&G4edX_5@dmKFFA#h}%YO;H2KW+(QUI#*YItnR}#Hfc^IWOUuo@(p$i0{#uBy zkF?y}Gu2=T4_uA$_`S4WEgk{p*{vDxCxHF;Ue5zFnR~Av0h|8UqW{OW zoH`ch9gWR=IuC~Z?Oz7WQvuW7mB>8l!wV_U$s&(ogX_B{6S0h!^>W?a;TW!~+PcZeFxxiAa+zMum9F?n$P0Mw7Pu9=D^pK_S1> z?Rc)QZ?|b+)%ERX?HjOqsBhJlFER_`j2<9UR-jyqe7>fLGE9niOheu2Ip^cTsK02^C%n@1UF zkoy%on#n|W+cDcgR#6`RO6`bg{PF;>5TIU+q}E=>+tH=k8MY8G3}0Z>sPK=XRlwqx^q>R-L+!nx>cA> zi~=4`o$Z&;yc!qvlz865V4hT*dZ*ki@13W#Yx}zR$FIdz_{)pyvo){6gP7V&<%S6p Mbs7hyDVOU13zcfVhX4Qo literal 15691 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 diff --git a/scripts/kconfig/conf.o b/scripts/kconfig/conf.o index c191a8a72cd7dc86b00872d436f45203e92698f7..fc7911451751f3d5917390039ba3ff2ed44769c2 100644 GIT binary patch literal 11136 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 PjPiQHWr7WYD+K=+%^6ML literal 10348 zcmcIpdvIITnLm~tFpfb6!lNWCH;J4$CQ;&qg%HT2II%+$f^6q)h^koEmi&-h=_-kL z32`f_AcR|5U>7Juli}UKl-<VCm?}Yf6m7XUPvLTeKv3xGHnx$`h8`H_%YxYuV&5)1!&9 z)@}Y*G(B*`vhmDIBV|WQ)f)G~bF(F*D}Au?5fw6{124{|Lzv8-SB6IV^~4#;rDVCR zvgF~)S0D+I)V7AoJcaEQ1$>T9>)bJ5%~Fj222WMi@=VD`n;Am9*?P}Q!;_OAl{{AB zPW==5KzwA9fkwrVNz(x;KeW`KwK=QvlssOx^UQJ2-4qY}oBnP5GCAgQe?JJf$>XQF zQ{RRA&G9Mh@egV&8Z+KIjqpq&1vI^gCupl9;< z=~hSbczNQXL#2)^^YTl_FKPPQcvI&0&4rP_ll-d0+JT=~L-H$EVzuq3Z)Ca8*Xb%y zOuU~QcUf0&+BA{-+QyBY6EZPi8;ICRLat^Y0+qV}VZmZafko@Et=cp4Mq#qkGpU-b zFZ1nV&(IY7`1J7hao$%v$lu(Fug1pWl`tchw@S_E}$6+xuD)pS*S!vH-wy`R^x>857x+!!Cw0$T0Y|b{6ZS{p%nA%3> zGLM59yQVQC>A^&6Q&Y>v;U6Iy_d#7kU?;~atm(jqf@K3_{{9yA^4$esO5S)LV%N3)HU&CS^r<-X9O0)^Zh^v$oQ zQ;m1CjJKtDycn(?kUM=h%h@T-%{o0>eVwg3i0rm09N!77n}?}}#`hlA4VOE0qe~Ae zJ;#<<=dmaXhnD`it*Rxi36g$DvJK_wL3jEs42Y$_*cq6U`mI}h8;55jQ`i9v3R_R; zq&bNn+u}|=Mh|0K_RLInFJ!pLsQ{qmKq83KJ#r+{U7ICKgO2^9Jn$sx3n}*oRM45P3o6}x{7hj zWarM;v)`!-ZKhsE2Wl=W)O?aLH8mB~Bd6j2oTPLs`q^uusj0d1x{(T>z4CmW>+(@t zOWQgh@cPX{uU!(#%0lMVVA|^^IkwK7eiW52H`oQc%F~+P>+f3Wxxi-IOD+8Z=WoN5LIj{ z-?~v+v$rVpv6Hu2)=ndoZ6~{{AhdV91#*I9*Lw`?{@l=1c58Y1PYHMKM{G~!y1xZ2 zm@nKh-_O=pqWn|8hp6GoF?VV$LhyAO`#@u3T8CflEHlmCh;T0YHinuVHhLq5tgkHn zx;y>v;AU489C8nX0e_tp&aCS&(%gQu{neXfOj{j$FouJ}o$5eZT3R-Sf{q}2T{&dw zU%AuI+D1d2j!2tg$FXwvEr-D!_oTVSpRE7rmo`5fszhW+&XQDMEYD(#Nh8UJL&A)is&* zo-$m5%6zDoWI;5!=@?%BO`gfhIySs#REH}EsQ9uE3t!Q3>TJJne>OgT+r=CoeD|Ng zaYrvHjQv%lSetMkd?TxP*DH6Yp2W7-sX8k#7IBO>zptGVQZzIh5aHpso`D0e!8DSf;r3Z~DUx*vMk`l@W4lY1T<^NyFglfB1E-Kp=Qksh_YqYa*_L?GKxnH(;K#?Ccx zo3{gnGwsDN=z0(xRJIibWSygR(k!Z}NE!Bo4{6HQ9JV#LwQl2ew`F+Q7|y9*=;loO zoJ-z3rNnwjE6C+|#RR9=Jhs!ez5{jEHs{xvcEGjv1B4<|YveA6?v)qs1$VZO84Vl)SK0ZoJktu!C#y5NtrA1ⅅe~ug|u4GOsy1ZQ_c39Q*oKG#o9fjGW#wo9p zBTvC_=mB_=;a25#p`&a>&Uuk}PoEgwJO)(q-H)<~%H;0ylAFtM8R}m=&#K8zdw@&% zYV3je@!GS+O|ER`T5NELW~R(J$e)H}G7O1tCl92w>!_ay9TMeQc{7yGd2EYUnYS?<&y5E3)(DrCL_<{>@Q z=WKC^1)w!@om?CGgQ%sYDYO^-Tr*hkd&-Aa_d&Yz~L9#8_h!Mtc~E=n2Q;;Yi0R#?DmKM6g}P+*6NO0rlh`3`2#=!+&|VrM#)bq8O!8Hk%k4C9YSdkRO2P-;wXhu4@fF)uTW zXiRst`8{SNVJD0NQQjq-Ihf_zS_~V%x=(!|GTTC4BEh0uNp6i9)$tj2bZQ?qw43B@ z0N#Q3<1>_cPu|}Ei{BT(yXY+Y{R+#I?Q4JsfG%L+`|&Awh4TNe_B-PDjUxZ2it#?^ zWbr;;pxc4=RRwfmoO8ifjrH|QjGD%E8|D~`yo@w;Wco*2B zd6)MDyXGk6jra9ff$cymW@E@{#msK6W$v<+7fT_ayxZe(<&8y2P`l1sH<4Vl5H$MO zD$0vWG`$FB9@c+b7uS3bYR3BdwNNbKJ)V0f&mcZ4@V@G1%YLc^rvfqk`RDM(N-f4g zR|yXL^Q7UqS1mNp8$JdMTyHmRTH2Qasqg6ZL+>Gx5e#WB0MhBwGYg?)q7OF2+%y$8qps%!T9q0t4$sCytlLw=>>Wv2&mn&KRf{3=DrpDUtyYjhs!|I#6Vq<>vRA1$JXi|D@=(PtDC2<=rB z(H9ocmlV;nis-pT^g__DVJ`j~w$DL6mlerdis(=g{hcEE)*||zBAS11bsmoAsUlim zRYigF-xbN<2Yn3lKa7|e??{n+6g217p5IT#Cqd77XwO|lUsy!XETS(hq8Ap?R}|69 zi)fzt&O`r-mkMv2!sUVI$BsaEIOvaC!Ei)HqP#Zy^)VGQtwb#1hd5y>98lq2)fO__ zx@a69?EkC>CQiboaJE zcboX~(~A}D_9G9t%m%vcj?6=EAch(B(~#;3Abg!-aO0-Jm6}wz!_UtETM{z^K|MFR zhgRlwnbWX~`BLF{z_R+374AW{B%kfJiq@u6xvTrhhyz0mayrDhN>QtApK4uMAD zCx9i`fAB&m{lr-)hj|jbAx-|w+Z#GC&C~9dqRI*!jB22M9#k&(Er24=}J9I#Gu{)(#|oVx!%b? z9qWuZ1xWc+!5M;Fx0G{zQqKQ9mCRIXI}!1OfG&?xJtB__K0?Hu{C5R&K=$KC$$2~t$Z@(!&qW->8A=5N_fQUhDbnb7 zI}!2UPd?uLg04w6eF4xlPpMkc@U@tT{!7V6|Mfy|5xR>Ae>V$1Dg3*HzE|jniHLVU z`PE82O&an3O6a44e-{3yq~Z5-((ro*?i!@e0+OyHjo8-;1_bvAW(DseR%70Q^na9y zI-h(x(2KeQa-0_tVc!s}rks9A!_Q*DAo;kI-9j4u28ihQWAdSY9}#vR68_`De~Y*P z^+rDWeJJuz1wW@8{m;ZkKzru^N!JKHPw0iDu|8K3u|7AD4}aT8!)`kf{kzCV|6M}w z7J5MF9}E4j#5$$^LPUHYi2P%bkCKMJxw!0e+zmkHV-0E4_j;j2q)|6_5E0M43 z8Xr3rX}o=;v2Wc;8gbn#{0GQKJiieBpx}Q99u*t`a{P<1$GYZVKLXNDqhMI@JA(HU zk+;Wy%*S)We_8O?g0B-{`zVlcyhj@2oQ%5?{mmevUY7#NuNS`M$g13wOUcm>6$kQ`K=pQ6P|5c&iBEsG~K-ZN@eIop_v%p9ElYy=!SeHcj_mU6& z6@u51e--MVH2ic6e<%4@{707;bNF(oyguj^lWjHrU!~S~G&SO9OBDES<2(A=dEx1Zx_5n z@Gil71n(EzEBKJ$V}efzJ|+0H-~quG1qTHW3%)A&8^PBE-xU0V;M;=71m6`L7W_c) yBf(Dv#{|C+RHz5$wM?*Fuu_oUos{#toXGD^;xs`+&?8tQ$nQ<+EfBm+@P7d&TLYf} diff --git a/scripts/kconfig/kxgettext.o b/scripts/kconfig/kxgettext.o index e92d2605cde62dcf3fe3b45158dcfacc8820a2ca..531fd720480cf020533b0b88f610cac502020982 100644 GIT binary patch literal 2416 zcma)7Yitx%6h8YvhGk$EL?yQBx=gi*Y<3CQh$yw&@`#9q(n0_`S$4N{%f7NRi`5uj zyOTH$O=_aXUncx8@duh1iGiqLrKCuVF_Nf1Fu{mOD~$n7YKZ9go!J?>>@ROJ^PTU! z?z!jQJ9DsW(>j;SMb2=Mhh`X2##^(jw4jydl0bbu<*9%^rhh*qPTVq0vwSw7RaH^n z;nfSmIm>b9uKuyn-tB!oho=^`6Tx|#6wtpO@^#Nd_}{AfKe>ME6f&66s($H@5C8gh z@a*8-rY%(X-#+oXA~dn#4+;nDI<*MX)rA%EpE z=3RrBPl2zwJ7OEzq4bkBtqPjy*KR;P?hcK2xX5@KGHIqNjqH}hk^NMj5_-(Gy22{o z!NE9)z|!UNlsFWyZ2FkBP=Dnsw!SF^+p(~TiQoS~9bBu&H{Rh5mCwv7PtJ;M zoO}$8g1v*6H`xrr{+-gi5MJ|rc=$1-0FHg+q)U?-u>$#K-W3qtP$G z_x@4ixqxk^8rY7xT=_;BycAC3-ZL|iTjrR3)8>?7_15`N-M9+BIDZ#YVLq4l2 zW1W{Psj3TL=^pgK(b7ZNZ7PDPcn9x=?wYv8W)C?YMiU2KEdAP;a>q{diNQy2yX_a) zZ@P437p{gr-K$?gK>3&J<*8<)OEe2!Yrb<{2@$oqb+2UUtXH&per#(#uLhq_#Wp6qO*#|*Ui@{I`%UK_btq!)X-`u-2xH23GM}sROkyVkl z6>Y)Rt*K;iLtL%tm#> z9Hnp~pUtLnaLMJ>R2XwESJZf7A1~~G4el+U*t=|R{`L%eYyz-9Nz?>+&WxH42}IXz z9mlgDRMdipxs&3!BS6Q)$+rwL`#Wa#b8Pi~5fIL|f|VHT_f$=^-fZJ%t&NrvudDD| z?vOg$hB}$ei|Qw>vn_z^)aLl@V8I?dCl5xqCDmRM8aWCjpX#}IIDG&Q_pUzQiP=Q_ zZF7c`&*2W%>%DZtbo7jO{ymu2&%oSE^Xve=9Bx$G3~a?Sjl|4x0) zYv3UiT{k>9HEngA*ZE8X?`q(i8hCF5-w7T>Lk-|UR8(xR9|1oO``fntjRyNW4g6RG ze;>RPZQ^sz`9El|pKRc?Z+LG?S&up8LNT8$AQf}jsRFr@ z`I1WV#uwy5Nlj3pn9ivKm@u8AL_Rkl7ve?5&dyni_>f@&e8@<|+T1vlyhm=3FMuv= z{141=Q2w;-kMP-;k2?iq`vx2TX1$+iHu}%_BqJ`$QATY3yFeE%^?Npc#EAGW8Sf_g z2IyWy^s{Zh%KRRjMVouEFC0Gy$oeMchzl`C+%nr9vF+O#?;}buE+*Q?h&l?43yJ;% Dsenp9 delta 1268 zcmYjPeP|nH7=P|7IpTG>ChayzinladD=Z;dyDDY6k<`s?=-Opl?NVDu*HJ5LyWM4o zh*6RguP=d(w;}^U#{N+d#D9j{bYyGEKK>Cah%k`Bu%xEK@FOspp3i%^U=QB=JvtAj9s*%!>XzNvbH-OQOerp6@0Uy4CjA{Go$-Gc38(pPyPHMtBx{;?H)%&LqhQ` zG9)XT_j3;mYs$3xKW8oaix(NY5bfQAP>d!Js*nG*ZL@5p6+_2@;dS|fks$+7#Y&5p zunh9I(=tOVEnAL&_m|j4vSZ^`^|eL3NrfLxtq$Nmm{H+p@I>(V3ab(`@jk0DWO0hE zE6q9RWtw)g;kTG&J6+BD{$d|GOmiNGHAU}rMBiX})-A(F(u&0=>sCf_TUdWJR9W?7 znZlY%Mx)`zl;b0|u8~aGT)xWgVhH4boLnBNc3?x2QP>if4KGQ_W;wUr*`u-HJkeFN zp3Aq85U%x)k?a_|?Rw!PRQm-#1vx9S?gzu>-D__5A^EWNd$s%zUVBNceTj9)GJ|9% zWAUTDjy@Sv25nuob#cmv(V8D)LvElA1I}_tsIYWU#px?#ugIj~G~4Mi?Q;@dJ#P0+ zg`4R(i=2~D^W`jx#oWQE#5%5alfEUq!1?GcVQc?(ZL8j&U=P5)bh=;b-uKGUXSAMp zZ+wTgBa!G$CX&x;-G?VnYA>BI8u3_P{M1Ab4Tz~tGqc8I94lhFabn_4h)>L(K0P^O z&@*BueNXhz1+k6mrk{(QQZN2J59s%3jS47+ZjpjikyLJ!c1T_Leo^X@K6aQhQn39H zrf_(g4`Y%P8Ty5!@^=J!L)ymwB+(UV8#hH;JbCU4EqQjfdYT0e3gD$bc#cXBuvLl1 zydi0h2Po2)yw^`f|@PUgphOGd9GafhdJnG_6#xNrD za}2Sbxc(;%9Dz${@IioUEPy}AP3E@)+-oGjcP_u;`Zd@0;sW_iD3IZ1fDl6*s4)xx F{0BH|qqqP7 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 61fe000c02c6b0f4616655879d4e953705e48b32..6efca8d51391595fa067dba6ae17da4b657699ff 100644 GIT binary patch literal 29292 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 literal 20532 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 Ln*@V`8wCFYs} #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 3d1d070f08e892bfbf6ad208776f231e4c1108b7..e14d898256a534dcfd4c3cbe442a5a23e47da158 100644 GIT binary patch literal 66344 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 literal 95696 zcmeFa3wTu3)i=H;8InjMGhkHIs0SPbEVm#k8Bvo!55fmpH-&c7m(cIi?0DVrk?=oDu=q49R(y)(6Uf5U z69K&I_m$w=xR2sXyq-hG;{-9Dq?CzSLyxV}FE2adyFC{?82`erk5%iB`vKYUB&G48 zM84bS_$hyS-*MEBkPSm61>`p#XWR_+^cqi6TK$N}^c>WmEF%BohmTS|Vnp=tk@5TW zZ@-4ukin&HG@j(Q#-0yBadf}mh|{}diGC#7nQJ^wyoetD&~wCioEV^U3?ok2>^Ynx z5$Jn9+>^}t=eLc=DMwjO<32)VJjuDw8+J_bkMSjD`9IX-#2Lw@#H>q>l|Adb?VmoB zhdJtd`iYs>qk5v|{o$p?qf`M#UbOF+FP4iq@lM~JuMZ>cQyt|1c-c5`Z=XS zUB+YaF<8i=dvYWnllOdt%6hY?*~1kovqZJ_ik$G6=$n33%|)TwTJ~PGG?d`%Lumov z;&J9wz4wu*j^AU%DOl%VPv`i(U`jbLMb;rligtQ;{DnCv17DOJ^F1BA@(wTfI#r6j z@9EPZnOw)0ai#e5Jyb1cP_>jD44+I4{4Q!Ec_u{C_w-{|5;yh7sh*N2Bgke*{9U3z zakWy1>{1*{a1u2)Ty_B>_-_9_kjZG>aW7(^z92XPJ`x$A0hB4sSl!5nA)Td!xrZsIyTAAM%8!ph}Dw3$bLh zksv})F^PEvK7;cq*Evk*mulp+^&x}FH6AB&fFas>rY=J=P~B&tn&tPY7XBeMyaauR ztop6(>7u~LmgqzZJu?6R35p|25pn@Sm=cQ@X)fGHyo+;LdiGI!+V77(NlhX*GRe{l z)MBeZW+)`<8QP87eW>T14;XKE9x3E*R?xX9V(NP1K2mFCEV#bdEl6u5NP1+GWO?k& z7oxGTA=L9dAd&4rw#n!lInkt7mqHJf`8YKZ*))7lUo0gxQx-{yC2Eusifw;_RglLQ z-@p={))%Yr&ibNnC5ApPcToj5gc91C;1kr<%#AYF>VC~T? znuSsEVW>GbgEWmv+j=~Vi-|PZtqG`pF@-Wc4uUl+`Db=E({5jHb4+-yehg?SlwAO2nl6fW+FNb^CET zPA#D~O? zRL$ItF;kD1RRKpRaut^M-ak&!f5{PwvRbiJFuRYJ_)bJ{@QoFWEM&Jg0GU!^z%9_K z=M~38T1H4+IR~WF)2IF`tvUSEW$c4t(Oq6ZJ%XdESY+SpJzn_{K@}l{dY}8DG^lKa zWQnfK(kjGPDHW?hYP1kV&KKex>L**xcGM7MFz4fCa2cgyCXmt?G=q~66%nM;3-#oq zyOTX6*ddbtcrOE*gvpcqvokF9hMhR|vWq%RtBvnM@mOlZOKO7#I;1vU1OJuUhy!(Y z9o)>>`3GiE4I(7M=Q|XpEIM~FD1KJ&C%c%lj)(Oh?^<<)0vaCKo|Au}P}%v)j-l;C z7L;EhykSs2e*-aWRweI2BYujwko+uRlvU-gLk$zb(rizL3B+PTBtTLetg%FC5u;6W zr=LklDwSQVf5)!K)$`tAYh~rf6{g8Z(kVvjc*%w9#oYgA} zk_j6`+>Ga=oidrpFaXlmOi>=EP6rLaW8}$l=v`Ll2tgvdCwT?MeeH zwkP$Hr5^ls#`?YnB_4WL(woi#_>B#Kc~Y+^T^oW7C^eV*jS_*j50k%n$Kp(_0eqyV zr4~+oUr}qJ@}~Zlu1qCQDP3Wjn(P3g(%xhgKTnZyk=#r^>R*$s@L^iRF%yAii10E0 zP|VTulK(h@(V4f6@#y`3jvyy1)g0SVuKIT=Je{n-2elbneHvgbmsaJ$jBLHF$@ z-3X~lG`)NEb<3{ZXU$F!$D?oOME~y9rG@(>g~$PC8PAZk*QmJ6b>Gu@wTRyl8%dUP zEf0k1LOrc-TYN$u(H;vK3w{|-2DJT*$Jti?rJc!}$qsfH4A~MTYaIBJFUs+*rNk;x z77Ctt99t)i;4WxEOb$6GghlgV@ViEJ zpm)C(c^!%Er18$k5QL|Gjlkxi7D7rDc@AR@no-;OZHc;@r`J%s`zWqdGL*5JFEeHZ zyv%^BcI<&bh>4`2qkV-N3ys*04`Gpdo;43Ac97`p`xk!f`M50p8sUK7xFt}0X*e)4 zTn37)*{7mVqb!|06bbdLN2an6r3b(-V@kC?MSqrxB13-$Qib7HEEHvxCE>#vC_@tE zRo7V~;hwXRLZ2Zm%VpLCNb277{9&dzNLeYjJ5yQj)MqQHvs6-IRvm`}MAPXZTG0$oRhSZyK$#)mw6vdb+l@ zUdCOr)WRCwU&1OQd%l(FDaxP+ya7#`v8kxHCgAtQeof?a!RnjyEqaWaBGhrTZwN_V zbOJ^dG^19p+E$(&ZR0pZgPa$o=5qU?mQoHb2Fj{SBL6U|3!;5qU+e>9L7v+wui3uX zEQm@7z9^D?ySltn#avLJcWs}MGcNqSlNBBbAj}?I#9yVoq>+et3Zu*P9X7FXJL&U7c0XdH9}aZ15uPIYu?nJ`_`~xxUyPs9c8n7#ev6Er*4Y<@p`P8~L8G)erPP1{0%w zIpJ`$4=KMyDQgJTWMV^^Rjv${EmUkEp|_Q6W25zwyb3jtF7Xqo*DNeHcfi2p)#>_d zwgF2Z?n{-NT(!i)NYQB?$P${o)Qj2rqFMDS-1T%vr(tyj>jOfMPJpjFItAbK(Q~?} zHyn9&zx5E8_Q|QxLIa+j#3s+BzaXUBf`&mT8|$I6$6>;d>@4FR!f$Y1o;N%_I={=j zIX~GHq?QbY8ZAXA)9H*@&qFCO3(QDTU+UjK6dS*w5}++6s+F!nwd(l|SoRqSqk;$l z3M0SEn;tvgCE`as5pc5@i_Dm+)pvNhD| zU-Ud{f`sDQp*hAqgc$RjC#x{;t%z`b&tJf+P-wL%Cn1$|8wO=16QB&bx1;AK%xlVY zx;J3_0yE8`BRU#M^^bPu8;=r^rJaf5-j4i4aRW5t;ki(r#UV_NFS;H|GTys&RL$TK zw!QrR|0v3e0=}p3ZP(@i`#8OCe2?zw$luAib>$14Gmjpv-nhny-E(+>)WFufDh6!| z$vD|S)tl;mb^q?Oz&I4jYJVFneH#5xcP$%DsON@LIJxAp zUK~jNo#s4L|7WZ&s?t{%B@ZEN_gG5$h26C3le&AiMn4_9N6}Ao_Za*nH$y~rpHIG4 zl3EML?4k;Nc2T;LlQF_ZlMcznj(EPOgbrb0L6ebT(~9H@LOPlvpGm&6$>)bJjnB>~ zR8*;liguq%QQo3FMw0Ic`OYNY>*PCwe19U}2=Z~sP9fj36gHfEPm#}0zQ@StBj3a1 z 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[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) { -- 2.43.0