diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2014-03-20 14:49:19 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2014-03-20 14:49:19 +0000 |
commit | da82fd65effce44be0da4142490d559d404a7c7a (patch) | |
tree | a1ca62c7eddba140fb9ba8d3f5434100de5076af /main | |
parent | a09553ac6c535ce804805e7f143d7daa932efa25 (diff) | |
download | aports-da82fd65effce44be0da4142490d559d404a7c7a.tar.bz2 aports-da82fd65effce44be0da4142490d559d404a7c7a.tar.xz |
main/linux-scst: deleted
obsolete
Diffstat (limited to 'main')
-rw-r--r-- | main/linux-scst/APKBUILD | 137 | ||||
-rw-r--r-- | main/linux-scst/kernelconfig.x86_64 | 5318 | ||||
-rw-r--r-- | main/linux-scst/scst-2.2.0-3.2.2.patch | 80901 |
3 files changed, 0 insertions, 86356 deletions
diff --git a/main/linux-scst/APKBUILD b/main/linux-scst/APKBUILD deleted file mode 100644 index 4876bc105..000000000 --- a/main/linux-scst/APKBUILD +++ /dev/null @@ -1,137 +0,0 @@ -# Maintainer: Natanael Copa <ncopa@alpinelinux.org> - -_flavor=scst -pkgname=linux-${_flavor} -pkgver=3.2.2 - -_scstver=2.2.0 - -if [ "${pkgver##*.*.*}" = "$pkgver" ]; then - _kernver=$pkgver -else - _kernver=${pkgver%.*} -fi - -pkgrel=1 -pkgdesc="Linux kernel with SCST" -url="http://scst.sourceforge.net" -depends="mkinitfs linux-firmware" -makedepends="perl sed installkernel" -options="!strip" -_config=${config:-kernelconfig.${CARCH}} -install= -source="http://www.kernel.org/pub/linux/kernel/v3.0/linux-$_kernver.tar.bz2 - http://www.kernel.org/pub/linux/kernel/v3.0/patch-$pkgver.bz2 - kernelconfig.x86_64 - scst-2.2.0-3.2.2.patch - " -subpackages="$pkgname-dev" -arch="x86_64" -license="GPL-2" - -_abi_release=${pkgver}-${_scstver} - -prepare() { - cd "$srcdir"/linux-$_kernver - if [ "$_kernver" != "$pkgver" ]; then - bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1 - fi - - # first apply patches in specified order - for i in $source; do - i=${i##*/} - case $i in - *.patch|*.diff) - msg "Applying $i..." - patch -s -p1 -i "$srcdir"/$i || return 1 - ;; - esac - done - - mkdir -p "$srcdir"/build - cp "$srcdir"/$_config "$srcdir"/build/.config || return 1 - make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="${CC:-gcc}" \ - silentoldconfig -} - -# this is so we can do: 'abuild menuconfig' to reconfigure kernel -menuconfig() { - cd "$srcdir"/build - make menuconfig - cp .config "$startdir"/$_config || return 1 -} - -build() { - cd "$srcdir"/build - export GCC_SPECS=hardenednopie.specs - make CC="${CC:-gcc}" \ - KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-Alpine" \ - || return 1 -} - -package() { - cd "$srcdir"/build - mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules - make -j1 modules_install install \ - INSTALL_MOD_PATH="$pkgdir" \ - INSTALL_PATH="$pkgdir"/boot \ - || return 1 - - rm -rf "$pkgdir"/lib/modules/*/build \ - "$pkgdir"/lib/modules/*/source - rm -rf "$pkgdir"/lib/firmware - - install -D include/config/kernel.release \ - "$pkgdir"/usr/share/kernel/$_flavor/kernel.release -} - -dev() { - # copy the only the parts that we really need for build 3rd party - # kernel modules and install those as /usr/src/linux-headers, - # simlar to what ubuntu does - # - # this way you dont need to install the 300-400 kernel sources to - # build a tiny kernel module - # - pkgdesc="Headers and script for third party modules for kernel" - local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release} - - # first we import config, run prepare to set up for building - # external modules, and create the scripts - mkdir -p "$dir" - cp "$srcdir"/$_config "$dir"/.config - make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="${CC:-gcc}" \ - silentoldconfig prepare scripts - - # remove the stuff that poits to real sources. we want 3rd party - # modules to believe this is the soruces - rm "$dir"/Makefile "$dir"/source - - # copy the needed stuff from real sources - # - # this is taken from ubuntu kernel build script - # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD - cd "$srcdir"/linux-$_kernver - find . -path './include/*' -prune -o -path './scripts/*' -prune \ - -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \ - -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \ - -o -name '*.lds' \) | cpio -pdm "$dir" - cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core - cp -a drivers/media/video/*.h "$dir"/drivers/media/video - cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends - cp -a scripts include "$dir" - find $(find arch -name include -type d -print) -type f \ - | cpio -pdm "$dir" - - install -Dm644 "$srcdir"/build/Module.symvers \ - "$dir"/Module.symvers - - mkdir -p "$subpkgdir"/lib/modules/${_abi_release} - ln -sf /usr/src/linux-headers-${_abi_release} \ - "$subpkgdir"/lib/modules/${_abi_release}/build -} - -md5sums="7ceb61f87c097fc17509844b71268935 linux-3.2.tar.bz2 -e9e53fba37c5e2afa4cdecab234120bd patch-3.2.2.bz2 -ef1fc8a0f776a9639a135ac58acd26ce kernelconfig.x86_64 -7fc262466073cc46e51630a2ca55eada scst-2.2.0-3.2.2.patch" diff --git a/main/linux-scst/kernelconfig.x86_64 b/main/linux-scst/kernelconfig.x86_64 deleted file mode 100644 index 117c48e29..000000000 --- a/main/linux-scst/kernelconfig.x86_64 +++ /dev/null @@ -1,5318 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.2.2 Kernel Configuration -# -CONFIG_64BIT=y -# CONFIG_X86_32 is not set -CONFIG_X86_64=y -CONFIG_X86=y -CONFIG_INSTRUCTION_DECODER=y -CONFIG_OUTPUT_FORMAT="elf64-x86-64" -CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_MMU=y -CONFIG_ZONE_DMA=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_GPIO=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y -CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y -CONFIG_HAVE_SETUP_PER_CPU_AREA=y -CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ZONE_DMA32=y -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_AUDIT_ARCH=y -CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y -CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y -CONFIG_HAVE_INTEL_TXT=y -CONFIG_X86_64_SMP=y -CONFIG_X86_HT=y -CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" -# CONFIG_KTIME_SCALAR is not set -CONFIG_ARCH_CPU_PROBE_RELEASE=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_HAVE_IRQ_WORK=y -CONFIG_IRQ_WORK=y - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_XZ=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_BZIP2 is not set -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_XZ is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_DEFAULT_HOSTNAME="(none)" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -# CONFIG_FHANDLE is not set -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -# CONFIG_AUDIT is not set -CONFIG_HAVE_GENERIC_HARDIRQS=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_HARDIRQS=y -CONFIG_HAVE_SPARSE_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_PENDING_IRQ=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_SPARSE_IRQ=y - -# -# RCU Subsystem -# -CONFIG_TREE_RCU=y -# CONFIG_PREEMPT_RCU is not set -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -CONFIG_RCU_FAST_NO_HZ=y -# CONFIG_TREE_RCU_TRACE is not set -CONFIG_IKCONFIG=m -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y -CONFIG_CGROUPS=y -# CONFIG_CGROUP_DEBUG is not set -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -# CONFIG_PROC_PID_CPUSET is not set -CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set -# CONFIG_CGROUP_PERF is not set -CONFIG_CGROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_NAMESPACES=y -CONFIG_UTS_NS=y -CONFIG_IPC_NS=y -CONFIG_USER_NS=y -CONFIG_PID_NS=y -CONFIG_NET_NS=y -CONFIG_SCHED_AUTOGROUP=y -CONFIG_MM_OWNER=y -# CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_RD_XZ=y -CONFIG_RD_LZO=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EXPERT=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_PCSPKR_PLATFORM=y -CONFIG_HAVE_PCSPKR_PLATFORM=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -CONFIG_PERF_COUNTERS=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y -# CONFIG_SLUB_DEBUG is not set -# CONFIG_COMPAT_BRK is not set -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m -# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set -CONFIG_HAVE_OPROFILE=y -CONFIG_KPROBES=y -# CONFIG_JUMP_LABEL is not set -CONFIG_OPTPROBES=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_KRETPROBES=y -CONFIG_USER_RETURN_NOTIFIER=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_ATTRS=y -CONFIG_USE_GENERIC_SMP_HELPERS=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y -CONFIG_HAVE_USER_RETURN_NOTIFIER=y -CONFIG_HAVE_PERF_EVENTS_NMI=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_STOP_MACHINE=y -CONFIG_BLOCK=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_BSGLIB=y -# CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_DEV_THROTTLING is not set -CONFIG_BLOCK_COMPAT=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=m -CONFIG_IOSCHED_CFQ=y -CONFIG_CFQ_GROUP_IOSCHED=y -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -CONFIG_PREEMPT_NOTIFIERS=y -CONFIG_PADATA=y -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -CONFIG_INLINE_SPIN_UNLOCK=y -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -CONFIG_INLINE_READ_UNLOCK=y -# CONFIG_INLINE_READ_UNLOCK_BH is not set -CONFIG_INLINE_READ_UNLOCK_IRQ=y -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -CONFIG_INLINE_WRITE_UNLOCK=y -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_FREEZER=y - -# -# Processor type and features -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y -CONFIG_SMP=y -CONFIG_X86_X2APIC=y -CONFIG_X86_MPPARSE=y -CONFIG_X86_EXTENDED_PLATFORM=y -# CONFIG_X86_VSMP is not set -CONFIG_SCHED_OMIT_FRAME_POINTER=y -CONFIG_PARAVIRT_GUEST=y -# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set -CONFIG_XEN=y -CONFIG_XEN_DOM0=y -CONFIG_XEN_PRIVILEGED_GUEST=y -CONFIG_XEN_PVHVM=y -CONFIG_XEN_MAX_DOMAIN_MEMORY=128 -CONFIG_XEN_SAVE_RESTORE=y -# CONFIG_XEN_DEBUG_FS is not set -CONFIG_KVM_CLOCK=y -CONFIG_KVM_GUEST=y -CONFIG_PARAVIRT=y -# CONFIG_PARAVIRT_SPINLOCKS is not set -CONFIG_PARAVIRT_CLOCK=y -# CONFIG_PARAVIRT_DEBUG is not set -CONFIG_NO_BOOTMEM=y -# CONFIG_MEMTEST is not set -# CONFIG_MK8 is not set -# CONFIG_MPSC is not set -# CONFIG_MCORE2 is not set -# CONFIG_MATOM is not set -CONFIG_GENERIC_CPU=y -CONFIG_X86_INTERNODE_CACHE_SHIFT=6 -CONFIG_X86_CMPXCHG=y -CONFIG_CMPXCHG_LOCAL=y -CONFIG_CMPXCHG_DOUBLE=y -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_XADD=y -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_TSC=y -CONFIG_X86_CMPXCHG64=y -CONFIG_X86_CMOV=y -CONFIG_X86_MINIMUM_CPU_FAMILY=64 -CONFIG_X86_DEBUGCTLMSR=y -# CONFIG_PROCESSOR_SELECT is not set -CONFIG_CPU_SUP_INTEL=y -CONFIG_CPU_SUP_AMD=y -CONFIG_CPU_SUP_CENTAUR=y -CONFIG_HPET_TIMER=y -CONFIG_HPET_EMULATE_RTC=y -CONFIG_DMI=y -CONFIG_GART_IOMMU=y -# CONFIG_CALGARY_IOMMU is not set -CONFIG_SWIOTLB=y -CONFIG_IOMMU_HELPER=y -# CONFIG_MAXSMP is not set -CONFIG_NR_CPUS=128 -CONFIG_SCHED_SMT=y -CONFIG_SCHED_MC=y -CONFIG_IRQ_TIME_ACCOUNTING=y -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_VOLUNTARY=y -# CONFIG_PREEMPT is not set -CONFIG_X86_LOCAL_APIC=y -CONFIG_X86_IO_APIC=y -# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set -# CONFIG_X86_MCE is not set -CONFIG_I8K=m -CONFIG_MICROCODE=m -CONFIG_MICROCODE_INTEL=y -CONFIG_MICROCODE_AMD=y -CONFIG_MICROCODE_OLD_INTERFACE=y -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -CONFIG_ARCH_PHYS_ADDR_T_64BIT=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_DIRECT_GBPAGES=y -# CONFIG_NUMA is not set -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM=y -CONFIG_HAVE_MEMORY_PRESENT=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_HAVE_MEMBLOCK=y -# CONFIG_MEMORY_HOTPLUG is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_COMPACTION=y -CONFIG_MIGRATION=y -CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -CONFIG_MMU_NOTIFIER=y -CONFIG_KSM=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -CONFIG_TRANSPARENT_HUGEPAGE=y -CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y -# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set -# CONFIG_CLEANCACHE is not set -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW=64 -CONFIG_MTRR=y -CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 -CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 -CONFIG_X86_PAT=y -CONFIG_ARCH_USES_PG_UNCACHED=y -CONFIG_ARCH_RANDOM=y -# CONFIG_EFI is not set -# CONFIG_SECCOMP is not set -# CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_HZ_100 is not set -# CONFIG_HZ_250 is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -CONFIG_HZ=300 -CONFIG_SCHED_HRTICK=y -# CONFIG_KEXEC is not set -# CONFIG_CRASH_DUMP is not set -CONFIG_PHYSICAL_START=0x1000000 -# CONFIG_RELOCATABLE is not set -CONFIG_PHYSICAL_ALIGN=0x1000000 -CONFIG_HOTPLUG_CPU=y -# CONFIG_COMPAT_VDSO is not set -# CONFIG_CMDLINE_BOOL is not set -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y - -# -# Power management and ACPI options -# -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_HIBERNATE_CALLBACKS=y -# CONFIG_HIBERNATION is not set -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -# CONFIG_PM_RUNTIME is not set -CONFIG_PM=y -# CONFIG_PM_DEBUG is not set -CONFIG_ACPI=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_PROCFS=y -CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_EC_DEBUGFS=y -CONFIG_ACPI_PROC_EVENT=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_VIDEO=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_DOCK=y -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_IPMI=m -CONFIG_ACPI_HOTPLUG_CPU=y -# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_THERMAL=m -# CONFIG_ACPI_CUSTOM_DSDT is not set -CONFIG_ACPI_BLACKLIST_YEAR=0 -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_PCI_SLOT=m -CONFIG_X86_PM_TIMER=y -CONFIG_ACPI_CONTAINER=m -CONFIG_ACPI_SBS=m -CONFIG_ACPI_HED=m -# CONFIG_ACPI_CUSTOM_METHOD is not set -CONFIG_ACPI_APEI=y -# CONFIG_ACPI_APEI_GHES is not set -CONFIG_ACPI_APEI_EINJ=m -CONFIG_ACPI_APEI_ERST_DEBUG=y -# CONFIG_SFI is not set - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=m -CONFIG_CPU_FREQ_STAT=m -# CONFIG_CPU_FREQ_STAT_DETAILS is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -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 - -# -# x86 CPU frequency scaling drivers -# -CONFIG_X86_PCC_CPUFREQ=m -CONFIG_X86_ACPI_CPUFREQ=m -CONFIG_X86_POWERNOW_K8=m -CONFIG_X86_SPEEDSTEP_CENTRINO=m -CONFIG_X86_P4_CLOCKMOD=m - -# -# shared options -# -CONFIG_X86_SPEEDSTEP_LIB=m -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_INTEL_IDLE=y - -# -# Memory power savings -# -CONFIG_I7300_IDLE_IOAT_CHANNEL=y -CONFIG_I7300_IDLE=m - -# -# Bus options (PCI etc.) -# -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_MMCONFIG=y -CONFIG_PCI_XEN=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_CNB20LE_QUIRK=y -CONFIG_PCIEPORTBUS=y -CONFIG_HOTPLUG_PCI_PCIE=m -# CONFIG_PCIEAER is not set -CONFIG_PCIEASPM=y -# CONFIG_PCIEASPM_DEBUG is not set -CONFIG_ARCH_SUPPORTS_MSI=y -CONFIG_PCI_MSI=y -# CONFIG_PCI_DEBUG is not set -CONFIG_PCI_STUB=m -CONFIG_XEN_PCIDEV_FRONTEND=m -CONFIG_HT_IRQ=y -CONFIG_PCI_ATS=y -CONFIG_PCI_IOV=y -CONFIG_PCI_PRI=y -CONFIG_PCI_PASID=y -CONFIG_PCI_IOAPIC=y -CONFIG_PCI_LABEL=y -CONFIG_ISA_DMA_API=y -CONFIG_AMD_NB=y -CONFIG_PCCARD=m -CONFIG_PCMCIA=m -CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_CARDBUS=y - -# -# PC-card bridges -# -CONFIG_YENTA=m -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_PCCARD_NONSTATIC=y -CONFIG_HOTPLUG_PCI=m -CONFIG_HOTPLUG_PCI_FAKE=m -CONFIG_HOTPLUG_PCI_ACPI=m -CONFIG_HOTPLUG_PCI_ACPI_IBM=m -CONFIG_HOTPLUG_PCI_CPCI=y -CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m -CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m -CONFIG_HOTPLUG_PCI_SHPC=m -# CONFIG_RAPIDIO is not set - -# -# Executable file formats / Emulations -# -CONFIG_BINFMT_ELF=y -CONFIG_COMPAT_BINFMT_ELF=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -# CONFIG_HAVE_AOUT is not set -CONFIG_BINFMT_MISC=m -CONFIG_IA32_EMULATION=y -# CONFIG_IA32_AOUT is not set -CONFIG_COMPAT=y -CONFIG_COMPAT_FOR_U64_ALIGNMENT=y -CONFIG_SYSVIPC_COMPAT=y -CONFIG_KEYS_COMPAT=y -CONFIG_HAVE_TEXT_POKE_SMP=y -CONFIG_NET=y -CONFIG_COMPAT_NETLINK_MESSAGES=y - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=m -CONFIG_XFRM_SUB_POLICY=y -CONFIG_XFRM_MIGRATE=y -# CONFIG_XFRM_STATISTICS is not set -CONFIG_XFRM_IPCOMP=m -CONFIG_NET_KEY=m -CONFIG_NET_KEY_MIGRATE=y -CONFIG_INET=y -CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -# CONFIG_IP_FIB_TRIE_STATS is not set -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_CLASSID=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE_DEMUX=y -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -# CONFIG_IP_PIMSM_V1 is not set -CONFIG_IP_PIMSM_V2=y -CONFIG_ARPD=y -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_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -CONFIG_INET_LRO=y -CONFIG_INET_DIAG=m -CONFIG_INET_TCP_DIAG=m -CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=m -CONFIG_TCP_CONG_CUBIC=y -CONFIG_TCP_CONG_WESTWOOD=m -CONFIG_TCP_CONG_HTCP=m -CONFIG_TCP_CONG_HSTCP=m -CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_VEGAS=m -CONFIG_TCP_CONG_SCALABLE=m -CONFIG_TCP_CONG_LP=m -CONFIG_TCP_CONG_VENO=m -CONFIG_TCP_CONG_YEAH=m -CONFIG_TCP_CONG_ILLINOIS=m -CONFIG_DEFAULT_CUBIC=y -# CONFIG_DEFAULT_RENO is not set -CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y -CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_MIP6=m -CONFIG_INET6_XFRM_TUNNEL=m -CONFIG_INET6_TUNNEL=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m -CONFIG_IPV6_SIT=m -CONFIG_IPV6_SIT_6RD=y -CONFIG_IPV6_NDISC_NODETYPE=y -CONFIG_IPV6_TUNNEL=m -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_MROUTE=y -CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -CONFIG_IPV6_PIMSM_V2=y -# CONFIG_NETLABEL is not set -CONFIG_NETWORK_SECMARK=y -CONFIG_NETWORK_PHY_TIMESTAMPING=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_NETFILTER_ADVANCED=y -CONFIG_BRIDGE_NETFILTER=y - -# -# Core Netfilter Configuration -# -CONFIG_NETFILTER_NETLINK=m -CONFIG_NETFILTER_NETLINK_QUEUE=m -CONFIG_NETFILTER_NETLINK_LOG=m -CONFIG_NF_CONNTRACK=m -CONFIG_NF_CONNTRACK_MARK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_ZONES=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_TIMESTAMP=y -CONFIG_NF_CT_PROTO_DCCP=m -CONFIG_NF_CT_PROTO_GRE=m -CONFIG_NF_CT_PROTO_SCTP=m -CONFIG_NF_CT_PROTO_UDPLITE=m -CONFIG_NF_CONNTRACK_AMANDA=m -CONFIG_NF_CONNTRACK_FTP=m -CONFIG_NF_CONNTRACK_H323=m -CONFIG_NF_CONNTRACK_IRC=m -CONFIG_NF_CONNTRACK_BROADCAST=m -CONFIG_NF_CONNTRACK_NETBIOS_NS=m -CONFIG_NF_CONNTRACK_SNMP=m -CONFIG_NF_CONNTRACK_PPTP=m -CONFIG_NF_CONNTRACK_SANE=m -CONFIG_NF_CONNTRACK_SIP=m -CONFIG_NF_CONNTRACK_TFTP=m -CONFIG_NF_CT_NETLINK=m -CONFIG_NETFILTER_TPROXY=m -CONFIG_NETFILTER_XTABLES=m - -# -# Xtables combined modules -# -CONFIG_NETFILTER_XT_MARK=m -CONFIG_NETFILTER_XT_CONNMARK=m -CONFIG_NETFILTER_XT_SET=m - -# -# Xtables targets -# -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m -CONFIG_NETFILTER_XT_TARGET_CT=m -CONFIG_NETFILTER_XT_TARGET_DSCP=m -CONFIG_NETFILTER_XT_TARGET_HL=m -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -CONFIG_NETFILTER_XT_TARGET_LED=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NFLOG=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -CONFIG_NETFILTER_XT_TARGET_RATEEST=m -CONFIG_NETFILTER_XT_TARGET_TEE=m -CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m -CONFIG_NETFILTER_XT_TARGET_SECMARK=m -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m - -# -# Xtables matches -# -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_CPU=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -CONFIG_NETFILTER_XT_MATCH_DSCP=m -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_HL=m -CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -CONFIG_NETFILTER_XT_MATCH_IPVS=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_OSF=m -CONFIG_NETFILTER_XT_MATCH_OWNER=m -CONFIG_NETFILTER_XT_MATCH_POLICY=m -CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m -CONFIG_NETFILTER_XT_MATCH_RATEEST=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_RECENT=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_SOCKET=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -CONFIG_NETFILTER_XT_MATCH_TIME=m -CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_IP_SET=m -CONFIG_IP_SET_MAX=256 -CONFIG_IP_SET_BITMAP_IP=m -CONFIG_IP_SET_BITMAP_IPMAC=m -CONFIG_IP_SET_BITMAP_PORT=m -CONFIG_IP_SET_HASH_IP=m -CONFIG_IP_SET_HASH_IPPORT=m -CONFIG_IP_SET_HASH_IPPORTIP=m -CONFIG_IP_SET_HASH_IPPORTNET=m -CONFIG_IP_SET_HASH_NET=m -CONFIG_IP_SET_HASH_NETPORT=m -CONFIG_IP_SET_HASH_NETIFACE=m -CONFIG_IP_SET_LIST_SET=m -CONFIG_IP_VS=m -CONFIG_IP_VS_IPV6=y -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_AH_ESP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y -CONFIG_IP_VS_PROTO_SCTP=y - -# -# IPVS scheduler -# -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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IP_VS_NFCT=y -CONFIG_IP_VS_PE_SIP=m - -# -# IP: Netfilter Configuration -# -CONFIG_NF_DEFRAG_IPV4=m -CONFIG_NF_CONNTRACK_IPV4=m -CONFIG_NF_CONNTRACK_PROC_COMPAT=y -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_AH=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_TTL=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_NF_NAT=m -CONFIG_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_NF_NAT_SNMP_BASIC=m -CONFIG_NF_NAT_PROTO_DCCP=m -CONFIG_NF_NAT_PROTO_GRE=m -CONFIG_NF_NAT_PROTO_UDPLITE=m -CONFIG_NF_NAT_PROTO_SCTP=m -CONFIG_NF_NAT_FTP=m -CONFIG_NF_NAT_IRC=m -CONFIG_NF_NAT_TFTP=m -CONFIG_NF_NAT_AMANDA=m -CONFIG_NF_NAT_PPTP=m -CONFIG_NF_NAT_H323=m -CONFIG_NF_NAT_SIP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_SECURITY=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_NF_DEFRAG_IPV6=m -CONFIG_NF_CONNTRACK_IPV6=m -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_AH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_MH=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m - -# -# DECnet: Netfilter Configuration -# -CONFIG_DECNET_NF_GRABULATOR=m -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_IP6=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 -CONFIG_BRIDGE_EBT_NFLOG=m -CONFIG_IP_DCCP=m -CONFIG_INET_DCCP_DIAG=m - -# -# DCCP CCIDs Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP_CCID2_DEBUG is not set -CONFIG_IP_DCCP_CCID3=y -# CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_TFRC_LIB=y - -# -# DCCP Kernel Hacking -# -# CONFIG_IP_DCCP_DEBUG is not set -# CONFIG_NET_DCCPPROBE is not set -CONFIG_IP_SCTP=m -CONFIG_NET_SCTPPROBE=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=y -# CONFIG_SCTP_HMAC_MD5 is not set -CONFIG_RDS=m -# CONFIG_RDS_RDMA is not set -# CONFIG_RDS_TCP is not set -# CONFIG_RDS_DEBUG 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=m -CONFIG_ATM_BR2684=m -# CONFIG_ATM_BR2684_IPFILTER is not set -CONFIG_L2TP=m -CONFIG_L2TP_DEBUGFS=m -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=m -CONFIG_L2TP_ETH=m -CONFIG_STP=m -CONFIG_BRIDGE=m -CONFIG_BRIDGE_IGMP_SNOOPING=y -# CONFIG_NET_DSA is not set -CONFIG_VLAN_8021Q=m -# CONFIG_VLAN_8021Q_GVRP is not set -CONFIG_DECNET=m -CONFIG_DECNET_ROUTER=y -CONFIG_LLC=m -CONFIG_LLC2=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=m -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_X25=m -CONFIG_LAPB=m -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -CONFIG_PHONET=m -CONFIG_IEEE802154=m -CONFIG_IEEE802154_6LOWPAN=m -CONFIG_NET_SCHED=y - -# -# Queueing/Scheduling -# -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_MULTIQ=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFB=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_DRR=m -CONFIG_NET_SCH_MQPRIO=m -CONFIG_NET_SCH_CHOKE=m -CONFIG_NET_SCH_QFQ=m -CONFIG_NET_SCH_INGRESS=m - -# -# Classification -# -CONFIG_NET_CLS=y -CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -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_CLS_FLOW=m -# CONFIG_NET_CLS_CGROUP is not set -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=y -CONFIG_NET_ACT_POLICE=m -CONFIG_NET_ACT_GACT=m -CONFIG_GACT_PROB=y -CONFIG_NET_ACT_MIRRED=m -CONFIG_NET_ACT_IPT=m -CONFIG_NET_ACT_NAT=m -CONFIG_NET_ACT_PEDIT=m -CONFIG_NET_ACT_SIMP=m -CONFIG_NET_ACT_SKBEDIT=m -CONFIG_NET_ACT_CSUM=m -# CONFIG_NET_CLS_IND is not set -CONFIG_NET_SCH_FIFO=y -# CONFIG_DCB is not set -CONFIG_DNS_RESOLVER=y -# CONFIG_BATMAN_ADV is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_HAVE_BPF_JIT=y -CONFIG_BPF_JIT=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -CONFIG_NET_TCPPROBE=m -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m - -# -# Dongle support -# -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 -CONFIG_KINGSUN_DONGLE=m -CONFIG_KSDAZZLE_DONGLE=m -CONFIG_KS959_DONGLE=m - -# -# FIR device drivers -# -CONFIG_USB_IRDA=m -CONFIG_SIGMATEL_FIR=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m -CONFIG_VIA_FIR=m -CONFIG_MCS_FIR=m -CONFIG_BT=m -CONFIG_BT_L2CAP=y -CONFIG_BT_SCO=y -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 - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIBTUSB=m -CONFIG_BT_HCIBTSDIO=m -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_ATH3K=y -CONFIG_BT_HCIUART_LL=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_BT_MRVL=m -CONFIG_BT_MRVL_SDIO=m -CONFIG_BT_ATH3K=m -CONFIG_BT_WILINK=m -CONFIG_AF_RXRPC=m -# CONFIG_AF_RXRPC_DEBUG is not set -CONFIG_RXKAD=m -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y -CONFIG_WEXT_SPY=y -CONFIG_WEXT_PRIV=y -CONFIG_CFG80211=m -# CONFIG_NL80211_TESTMODE is not set -# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set -# CONFIG_CFG80211_REG_DEBUG is not set -CONFIG_CFG80211_DEFAULT_PS=y -# CONFIG_CFG80211_DEBUGFS is not set -# CONFIG_CFG80211_INTERNAL_REGDB is not set -CONFIG_CFG80211_WEXT=y -CONFIG_WIRELESS_EXT_SYSFS=y -CONFIG_LIB80211=m -CONFIG_LIB80211_CRYPT_WEP=m -CONFIG_LIB80211_CRYPT_CCMP=m -CONFIG_LIB80211_CRYPT_TKIP=m -# CONFIG_LIB80211_DEBUG is not set -CONFIG_MAC80211=m -CONFIG_MAC80211_HAS_RC=y -CONFIG_MAC80211_RC_PID=y -CONFIG_MAC80211_RC_MINSTREL=y -CONFIG_MAC80211_RC_MINSTREL_HT=y -CONFIG_MAC80211_RC_DEFAULT_PID=y -# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set -CONFIG_MAC80211_RC_DEFAULT="pid" -# CONFIG_MAC80211_MESH is not set -CONFIG_MAC80211_LEDS=y -# CONFIG_MAC80211_DEBUGFS is not set -# CONFIG_MAC80211_DEBUG_MENU is not set -CONFIG_WIMAX=m -CONFIG_WIMAX_DEBUG_LEVEL=8 -CONFIG_RFKILL=m -CONFIG_RFKILL_LEDS=y -# CONFIG_RFKILL_INPUT is not set -CONFIG_NET_9P=m -CONFIG_NET_9P_VIRTIO=m -CONFIG_NET_9P_RDMA=m -# CONFIG_NET_9P_DEBUG is not set -# CONFIG_CAIF is not set -CONFIG_CEPH_LIB=m -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set -# CONFIG_NFC is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -CONFIG_FW_LOADER=m -# CONFIG_FIRMWARE_IN_KERNEL is not set -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -CONFIG_DEBUG_DEVRES=y -CONFIG_SYS_HYPERVISOR=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=m -CONFIG_REGMAP_SPI=m -CONFIG_CONNECTOR=m -CONFIG_MTD=m -CONFIG_MTD_TESTS=m -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_AR7_PARTS=m - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_HAVE_MTD_OTP=y -CONFIG_MTD_BLKDEVS=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 -CONFIG_SSFDC=m -CONFIG_SM_FTL=m -CONFIG_MTD_OOPS=m -CONFIG_MTD_SWAP=m - -# -# RAM/ROM/Flash chip drivers -# -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 - -# -# Mapping drivers for chip access -# -CONFIG_MTD_COMPLEX_MAPPINGS=y -CONFIG_MTD_PHYSMAP=m -# CONFIG_MTD_PHYSMAP_COMPAT is not set -CONFIG_MTD_SC520CDP=m -CONFIG_MTD_NETSC520=m -CONFIG_MTD_TS5500=m -CONFIG_MTD_SBC_GXX=m -CONFIG_MTD_AMD76XROM=m -CONFIG_MTD_ICHXROM=m -CONFIG_MTD_ESB2ROM=m -CONFIG_MTD_CK804XROM=m -CONFIG_MTD_SCB2_FLASH=m -CONFIG_MTD_NETtel=m -CONFIG_MTD_L440GX=m -CONFIG_MTD_PCI=m -CONFIG_MTD_PCMCIA=m -# CONFIG_MTD_PCMCIA_ANONYMOUS is not set -# CONFIG_MTD_GPIO_ADDR is not set -CONFIG_MTD_INTEL_VR_NOR=m -CONFIG_MTD_PLATRAM=m -# CONFIG_MTD_LATCH_ADDR is not set - -# -# Self-contained MTD device drivers -# -CONFIG_MTD_PMC551=m -CONFIG_MTD_PMC551_BUGFIX=y -# CONFIG_MTD_PMC551_DEBUG is not set -CONFIG_MTD_DATAFLASH=m -# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set -# CONFIG_MTD_DATAFLASH_OTP is not set -CONFIG_MTD_M25P80=m -CONFIG_M25PXX_USE_FAST_READ=y -# CONFIG_MTD_SST25L is not set -CONFIG_MTD_SLRAM=m -CONFIG_MTD_PHRAM=m -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTD_BLOCK2MTD=m - -# -# Disk-On-Chip Device Drivers -# -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOC2001PLUS=m -# CONFIG_MTD_DOCG3 is not set -CONFIG_MTD_DOCPROBE=m -CONFIG_MTD_DOCECC=m -CONFIG_MTD_DOCPROBE_ADVANCED=y -CONFIG_MTD_DOCPROBE_ADDRESS=0x0000 -# CONFIG_MTD_DOCPROBE_HIGH is not set -# CONFIG_MTD_DOCPROBE_55AA is not set -CONFIG_MTD_NAND_ECC=m -CONFIG_MTD_NAND_ECC_SMC=y -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_BCH is not set -CONFIG_MTD_SM_COMMON=m -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -CONFIG_MTD_NAND_DENALI=m -CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018 -CONFIG_MTD_NAND_IDS=m -CONFIG_MTD_NAND_RICOH=m -CONFIG_MTD_NAND_DISKONCHIP=m -# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set -CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 -# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set -CONFIG_MTD_NAND_CAFE=m -CONFIG_MTD_NAND_NANDSIM=m -CONFIG_MTD_NAND_PLATFORM=m -CONFIG_MTD_ALAUDA=m -CONFIG_MTD_ONENAND=m -# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set -# CONFIG_MTD_ONENAND_GENERIC is not set -CONFIG_MTD_ONENAND_OTP=y -CONFIG_MTD_ONENAND_2X_PROGRAM=y -CONFIG_MTD_ONENAND_SIM=m - -# -# LPDDR flash memory drivers -# -CONFIG_MTD_LPDDR=m -CONFIG_MTD_QINFO_PROBE=m -CONFIG_MTD_UBI=m -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTD_UBI_BEB_RESERVE=1 -# CONFIG_MTD_UBI_GLUEBI is not set -# CONFIG_MTD_UBI_DEBUG is not set -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_GSC is not set -CONFIG_PARPORT_AX88796=m -# CONFIG_PARPORT_1284 is not set -CONFIG_PARPORT_NOT_PC=y -CONFIG_PNP=y -# CONFIG_PNP_DEBUG_MESSAGES is not set - -# -# Protocols -# -CONFIG_PNPACPI=y -CONFIG_BLK_DEV=y -CONFIG_BLK_DEV_FD=m -# 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_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -CONFIG_BLK_DEV_CRYPTOLOOP=m -# CONFIG_BLK_DEV_DRBD is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_OSD=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=4096 -# CONFIG_BLK_DEV_XIP is not set -CONFIG_CDROM_PKTCDVD=m -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=m -CONFIG_XEN_BLKDEV_FRONTEND=y -CONFIG_XEN_BLKDEV_BACKEND=m -CONFIG_VIRTIO_BLK=m -# CONFIG_BLK_DEV_HD is not set -# CONFIG_BLK_DEV_RBD is not set -CONFIG_SENSORS_LIS3LV02D=m -CONFIG_MISC_DEVICES=y -CONFIG_AD525X_DPOT=m -CONFIG_AD525X_DPOT_I2C=m -CONFIG_AD525X_DPOT_SPI=m -CONFIG_IBM_ASM=m -CONFIG_PHANTOM=m -# CONFIG_INTEL_MID_PTI is not set -CONFIG_SGI_IOC4=m -CONFIG_TIFM_CORE=m -CONFIG_TIFM_7XX1=m -CONFIG_ICS932S401=m -CONFIG_ENCLOSURE_SERVICES=m -CONFIG_CS5535_MFGPT=m -CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7 -CONFIG_CS5535_CLOCK_EVENT_SRC=m -CONFIG_HP_ILO=m -CONFIG_APDS9802ALS=m -CONFIG_ISL29003=m -CONFIG_ISL29020=m -CONFIG_SENSORS_TSL2550=m -CONFIG_SENSORS_BH1780=m -CONFIG_SENSORS_BH1770=m -CONFIG_SENSORS_APDS990X=m -CONFIG_HMC6352=m -CONFIG_DS1682=m -CONFIG_TI_DAC7512=m -CONFIG_VMWARE_BALLOON=m -CONFIG_BMP085=m -CONFIG_PCH_PHUB=m -# CONFIG_USB_SWITCH_FSA9480 is not set -CONFIG_C2PORT=m -CONFIG_C2PORT_DURAMAR_2150=m - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=m -CONFIG_EEPROM_AT25=m -CONFIG_EEPROM_LEGACY=m -CONFIG_EEPROM_MAX6875=m -CONFIG_EEPROM_93CX6=m -CONFIG_EEPROM_93XX46=m -CONFIG_CB710_CORE=m -# CONFIG_CB710_DEBUG is not set -CONFIG_CB710_DEBUG_ASSUMPTIONS=y -CONFIG_IWMC3200TOP=m -# CONFIG_IWMC3200TOP_DEBUG is not set -# CONFIG_IWMC3200TOP_DEBUGFS is not set - -# -# Texas Instruments shared transport line discipline -# -CONFIG_TI_ST=m -CONFIG_SENSORS_LIS3_I2C=m - -# -# Altera FPGA firmware download module -# -# CONFIG_ALTERA_STAPL is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=m -CONFIG_RAID_ATTRS=m -CONFIG_SCSI=m -CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m -CONFIG_SCSI_NETLINK=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -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 -CONFIG_SCSI_ENCLOSURE=m -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=m -CONFIG_SCSI_FC_TGT_ATTRS=y -CONFIG_SCSI_ISCSI_ATTRS=m -CONFIG_SCSI_SAS_ATTRS=m -CONFIG_SCSI_SAS_LIBSAS=m -CONFIG_SCSI_SAS_ATA=y -CONFIG_SCSI_SAS_HOST_SMP=y -CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y -CONFIG_SCSI_LOWLEVEL=y -CONFIG_ISCSI_TCP=m -CONFIG_ISCSI_BOOT_SYSFS=m -CONFIG_SCSI_CXGB3_ISCSI=m -CONFIG_SCSI_CXGB4_ISCSI=m -CONFIG_SCSI_BNX2_ISCSI=m -CONFIG_SCSI_BNX2X_FCOE=m -CONFIG_BE2ISCSI=m -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_HPSA=m -CONFIG_SCSI_3W_9XXX=m -CONFIG_SCSI_3W_SAS=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -CONFIG_AIC7XXX_DEBUG_ENABLE=y -CONFIG_AIC7XXX_DEBUG_MASK=0 -CONFIG_AIC7XXX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -CONFIG_AIC79XX_DEBUG_ENABLE=y -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_AIC79XX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC94XX=m -# CONFIG_AIC94XX_DEBUG is not set -CONFIG_SCSI_MVSAS=m -CONFIG_SCSI_MVSAS_DEBUG=y -CONFIG_SCSI_MVSAS_TASKLET=y -CONFIG_SCSI_MVUMI=m -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_ARCMSR=m -CONFIG_MEGARAID_NEWGEN=y -CONFIG_MEGARAID_MM=m -CONFIG_MEGARAID_MAILBOX=m -CONFIG_MEGARAID_LEGACY=m -CONFIG_MEGARAID_SAS=m -CONFIG_SCSI_MPT2SAS=m -CONFIG_SCSI_MPT2SAS_MAX_SGE=128 -# CONFIG_SCSI_MPT2SAS_LOGGING is not set -CONFIG_SCSI_HPTIOP=m -CONFIG_SCSI_BUSLOGIC=m -CONFIG_VMWARE_PVSCSI=m -CONFIG_LIBFC=m -CONFIG_LIBFCOE=m -CONFIG_FCOE=m -CONFIG_FCOE_FNIC=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_EATA=m -# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_ISCI=m -CONFIG_SCSI_IPS=m -CONFIG_SCSI_INITIO=m -CONFIG_SCSI_INIA100=m -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -CONFIG_SCSI_STEX=m -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=m -CONFIG_SCSI_IPR_TRACE=y -# CONFIG_SCSI_IPR_DUMP is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_QLA_FC=m -CONFIG_SCSI_QLA_ISCSI=m -CONFIG_SCSI_LPFC=m -# CONFIG_SCSI_LPFC_DEBUG_FS is not set -CONFIG_SCSI_DC395x=m -CONFIG_SCSI_DC390T=m -CONFIG_SCSI_DEBUG=m -# CONFIG_SCSI_PMCRAID is not set -CONFIG_SCSI_PM8001=m -CONFIG_SCSI_SRP=m -# CONFIG_SCSI_BFA_FC is not set -# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set -CONFIG_SCSI_DH=m -CONFIG_SCSI_DH_RDAC=m -CONFIG_SCSI_DH_HP_SW=m -CONFIG_SCSI_DH_EMC=m -CONFIG_SCSI_DH_ALUA=m -CONFIG_SCSI_OSD_INITIATOR=m -CONFIG_SCSI_OSD_ULD=m -CONFIG_SCSI_OSD_DPRINT_SENSE=1 -# CONFIG_SCSI_OSD_DEBUG is not set - -# -# SCSI target (SCST) support -# -CONFIG_SCST=m -CONFIG_SCST_DISK=m -CONFIG_SCST_TAPE=m -CONFIG_SCST_CDROM=m -CONFIG_SCST_MODISK=m -CONFIG_SCST_CHANGER=m -CONFIG_SCST_PROCESSOR=m -CONFIG_SCST_RAID=m -CONFIG_SCST_VDISK=m -CONFIG_SCST_USER=m -# CONFIG_SCST_STRICT_SERIALIZING is not set -# CONFIG_SCST_STRICT_SECURITY is not set -# CONFIG_SCST_TEST_IO_IN_SIRQ is not set -# CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING is not set -# CONFIG_SCST_USE_EXPECTED_VALUES is not set -# CONFIG_SCST_EXTRACHECKS is not set -CONFIG_SCST_TRACING=y -# CONFIG_SCST_DEBUG is not set -# CONFIG_SCST_DEBUG_OOM is not set -# CONFIG_SCST_DEBUG_RETRY is not set -# CONFIG_SCST_DEBUG_SN is not set -# CONFIG_SCST_MEASURE_LATENCY is not set -CONFIG_SCST_ISCSI=m -# CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES is not set -CONFIG_SCST_LOCAL=m -# CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING is not set -CONFIG_SCST_SRPT=m -CONFIG_ATA=m -# CONFIG_ATA_NONSTANDARD is not set -CONFIG_ATA_VERBOSE_ERROR=y -CONFIG_ATA_ACPI=y -CONFIG_SATA_PMP=y - -# -# Controllers with non-SFF native interface -# -CONFIG_SATA_AHCI=m -CONFIG_SATA_AHCI_PLATFORM=m -CONFIG_SATA_INIC162X=m -CONFIG_SATA_ACARD_AHCI=m -CONFIG_SATA_SIL24=m -CONFIG_ATA_SFF=y - -# -# SFF controllers with custom DMA interface -# -CONFIG_PDC_ADMA=m -CONFIG_SATA_QSTOR=m -CONFIG_SATA_SX4=m -CONFIG_ATA_BMDMA=y - -# -# SATA SFF controllers with BMDMA -# -CONFIG_ATA_PIIX=m -CONFIG_SATA_MV=m -CONFIG_SATA_NV=m -CONFIG_SATA_PROMISE=m -CONFIG_SATA_SIL=m -CONFIG_SATA_SIS=m -CONFIG_SATA_SVW=m -CONFIG_SATA_ULI=m -CONFIG_SATA_VIA=m -CONFIG_SATA_VITESSE=m - -# -# PATA SFF controllers with BMDMA -# -CONFIG_PATA_ALI=m -CONFIG_PATA_AMD=m -CONFIG_PATA_ARASAN_CF=m -CONFIG_PATA_ARTOP=m -CONFIG_PATA_ATIIXP=m -CONFIG_PATA_ATP867X=m -CONFIG_PATA_CMD64X=m -CONFIG_PATA_CS5520=m -CONFIG_PATA_CS5530=m -CONFIG_PATA_CS5536=m -CONFIG_PATA_CYPRESS=m -CONFIG_PATA_EFAR=m -CONFIG_PATA_HPT366=m -CONFIG_PATA_HPT37X=m -CONFIG_PATA_HPT3X2N=m -CONFIG_PATA_HPT3X3=m -CONFIG_PATA_HPT3X3_DMA=y -CONFIG_PATA_IT8213=m -CONFIG_PATA_IT821X=m -CONFIG_PATA_JMICRON=m -CONFIG_PATA_MARVELL=m -CONFIG_PATA_NETCELL=m -CONFIG_PATA_NINJA32=m -CONFIG_PATA_NS87415=m -CONFIG_PATA_OLDPIIX=m -CONFIG_PATA_OPTIDMA=m -CONFIG_PATA_PDC2027X=m -CONFIG_PATA_PDC_OLD=m -CONFIG_PATA_RADISYS=m -CONFIG_PATA_RDC=m -CONFIG_PATA_SC1200=m -CONFIG_PATA_SCH=m -CONFIG_PATA_SERVERWORKS=m -CONFIG_PATA_SIL680=m -CONFIG_PATA_SIS=m -CONFIG_PATA_TOSHIBA=m -CONFIG_PATA_TRIFLEX=m -CONFIG_PATA_VIA=m -CONFIG_PATA_WINBOND=m - -# -# PIO-only SFF controllers -# -CONFIG_PATA_CMD640_PCI=m -CONFIG_PATA_MPIIX=m -CONFIG_PATA_NS87410=m -CONFIG_PATA_OPTI=m -CONFIG_PATA_PCMCIA=m -CONFIG_PATA_PLATFORM=m -CONFIG_PATA_RZ1000=m - -# -# Generic fallback / legacy drivers -# -CONFIG_PATA_ACPI=m -CONFIG_ATA_GENERIC=m -CONFIG_PATA_LEGACY=m -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -# CONFIG_MD_AUTODETECT is not set -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID10=m -CONFIG_MD_RAID456=m -# CONFIG_MULTICORE_RAID456 is not set -CONFIG_MD_MULTIPATH=m -CONFIG_MD_FAULTY=m -CONFIG_BLK_DEV_DM=m -# CONFIG_DM_DEBUG is not set -CONFIG_DM_BUFIO=m -CONFIG_DM_PERSISTENT_DATA=m -CONFIG_DM_CRYPT=m -CONFIG_DM_SNAPSHOT=m -CONFIG_DM_THIN_PROVISIONING=m -# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set -# CONFIG_DM_DEBUG_SPACE_MAPS is not set -CONFIG_DM_MIRROR=m -CONFIG_DM_RAID=m -CONFIG_DM_LOG_USERSPACE=m -CONFIG_DM_ZERO=m -CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_QL=m -CONFIG_DM_MULTIPATH_ST=m -CONFIG_DM_DELAY=m -# CONFIG_DM_UEVENT is not set -CONFIG_DM_FLAKEY=m -CONFIG_TARGET_CORE=m -CONFIG_TCM_IBLOCK=m -CONFIG_TCM_FILEIO=m -CONFIG_TCM_PSCSI=m -CONFIG_LOOPBACK_TARGET=m -CONFIG_TCM_FC=m -CONFIG_ISCSI_TARGET=m -CONFIG_FUSION=y -CONFIG_FUSION_SPI=m -CONFIG_FUSION_FC=m -CONFIG_FUSION_SAS=m -CONFIG_FUSION_MAX_SGE=128 -CONFIG_FUSION_CTL=m -# CONFIG_FUSION_LOGGING is not set - -# -# IEEE 1394 (FireWire) support -# -CONFIG_FIREWIRE=m -CONFIG_FIREWIRE_OHCI=m -CONFIG_FIREWIRE_OHCI_DEBUG=y -CONFIG_FIREWIRE_SBP2=m -CONFIG_FIREWIRE_NET=m -CONFIG_FIREWIRE_NOSY=m -CONFIG_I2O=m -CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y -CONFIG_I2O_EXT_ADAPTEC=y -CONFIG_I2O_EXT_ADAPTEC_DMA64=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 -# CONFIG_MACINTOSH_DRIVERS is not set -CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -CONFIG_BONDING=m -CONFIG_DUMMY=m -CONFIG_EQUALIZER=m -# CONFIG_NET_FC is not set -CONFIG_MII=m -CONFIG_IEEE802154_DRIVERS=m -CONFIG_IEEE802154_FAKEHARD=m -CONFIG_IFB=m -CONFIG_MACVLAN=m -CONFIG_MACVTAP=m -CONFIG_NETCONSOLE=m -CONFIG_NETCONSOLE_DYNAMIC=y -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y -CONFIG_TUN=m -CONFIG_VETH=m -CONFIG_VIRTIO_NET=m -CONFIG_SUNGEM_PHY=m -CONFIG_ARCNET=m -CONFIG_ARCNET_1201=m -CONFIG_ARCNET_1051=m -CONFIG_ARCNET_RAW=m -CONFIG_ARCNET_CAP=m -CONFIG_ARCNET_COM90xx=m -CONFIG_ARCNET_COM90xxIO=m -CONFIG_ARCNET_RIM_I=m -CONFIG_ARCNET_COM20020=m -CONFIG_ARCNET_COM20020_PCI=m -CONFIG_ARCNET_COM20020_CS=m -CONFIG_ATM_DRIVERS=y -CONFIG_ATM_DUMMY=m -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=m -# CONFIG_ATM_ZATM_DEBUG 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=m -# CONFIG_ATM_IA_DEBUG is not set -CONFIG_ATM_FORE200E=m -CONFIG_ATM_FORE200E_USE_TASKLET=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_HE=m -CONFIG_ATM_HE_USE_SUNI=y -CONFIG_ATM_SOLOS=m - -# -# CAIF transport drivers -# -CONFIG_ETHERNET=y -CONFIG_MDIO=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_3C589=m -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_NET_VENDOR_ADAPTEC=y -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_NET_VENDOR_ALTEON=y -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_NET_VENDOR_AMD=y -CONFIG_AMD8111_ETH=m -CONFIG_PCNET32=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_NET_VENDOR_ATHEROS=y -CONFIG_ATL2=m -CONFIG_ATL1=m -CONFIG_ATL1E=m -CONFIG_ATL1C=m -CONFIG_NET_VENDOR_BROADCOM=y -CONFIG_B44=m -CONFIG_B44_PCI_AUTOSELECT=y -CONFIG_B44_PCICORE_AUTOSELECT=y -CONFIG_B44_PCI=y -CONFIG_BNX2=m -CONFIG_CNIC=m -CONFIG_TIGON3=m -CONFIG_BNX2X=m -CONFIG_NET_VENDOR_BROCADE=y -CONFIG_BNA=m -CONFIG_NET_VENDOR_CHELSIO=y -CONFIG_CHELSIO_T1=m -CONFIG_CHELSIO_T1_1G=y -CONFIG_CHELSIO_T3=m -CONFIG_CHELSIO_T4=m -CONFIG_CHELSIO_T4VF=m -CONFIG_NET_VENDOR_CISCO=y -CONFIG_ENIC=m -CONFIG_DNET=m -CONFIG_NET_VENDOR_DEC=y -CONFIG_NET_TULIP=y -CONFIG_DE2104X=m -CONFIG_DE2104X_DSL=0 -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -# CONFIG_TULIP_NAPI is not set -CONFIG_DE4X5=m -CONFIG_WINBOND_840=m -CONFIG_DM9102=m -CONFIG_ULI526X=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_NET_VENDOR_DLINK=y -CONFIG_DE600=m -CONFIG_DE620=m -CONFIG_DL2K=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_NET_VENDOR_EMULEX=y -CONFIG_BE2NET=m -CONFIG_NET_VENDOR_EXAR=y -CONFIG_S2IO=m -CONFIG_VXGE=m -# CONFIG_VXGE_DEBUG_TRACE_ALL is not set -CONFIG_NET_VENDOR_FUJITSU=y -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_NET_VENDOR_HP=y -CONFIG_HP100=m -CONFIG_NET_VENDOR_INTEL=y -CONFIG_E100=m -CONFIG_E1000=m -CONFIG_E1000E=m -CONFIG_IGB=m -CONFIG_IGB_DCA=y -CONFIG_IGBVF=m -CONFIG_IXGB=m -CONFIG_IXGBE=m -CONFIG_IXGBE_DCA=y -# CONFIG_IXGBEVF is not set -CONFIG_NET_VENDOR_I825XX=y -# CONFIG_ZNET is not set -CONFIG_IP1000=m -CONFIG_JME=m -CONFIG_NET_VENDOR_MARVELL=y -CONFIG_SKGE=m -# CONFIG_SKGE_DEBUG is not set -CONFIG_SKGE_GENESIS=y -CONFIG_SKY2=m -# CONFIG_SKY2_DEBUG is not set -CONFIG_NET_VENDOR_MELLANOX=y -CONFIG_MLX4_EN=m -CONFIG_MLX4_CORE=m -CONFIG_MLX4_DEBUG=y -CONFIG_NET_VENDOR_MICREL=y -CONFIG_KS8842=m -CONFIG_KS8851=m -CONFIG_KS8851_MLL=m -CONFIG_KSZ884X_PCI=m -CONFIG_NET_VENDOR_MICROCHIP=y -CONFIG_ENC28J60=m -# CONFIG_ENC28J60_WRITEVERIFY is not set -CONFIG_NET_VENDOR_MYRI=y -CONFIG_MYRI10GE=m -CONFIG_MYRI10GE_DCA=y -CONFIG_FEALNX=m -CONFIG_NET_VENDOR_NATSEMI=y -CONFIG_NATSEMI=m -CONFIG_NS83820=m -CONFIG_NET_VENDOR_8390=y -CONFIG_PCMCIA_AXNET=m -CONFIG_NE2K_PCI=m -CONFIG_PCMCIA_PCNET=m -CONFIG_NET_VENDOR_NVIDIA=y -CONFIG_FORCEDETH=m -CONFIG_NET_VENDOR_OKI=y -CONFIG_PCH_GBE=m -CONFIG_ETHOC=m -CONFIG_NET_PACKET_ENGINE=y -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_NET_VENDOR_QLOGIC=y -CONFIG_QLA3XXX=m -CONFIG_QLCNIC=m -CONFIG_QLGE=m -CONFIG_NETXEN_NIC=m -CONFIG_NET_VENDOR_REALTEK=y -CONFIG_ATP=m -CONFIG_8139CP=m -CONFIG_8139TOO=m -CONFIG_8139TOO_PIO=y -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set -CONFIG_R8169=m -CONFIG_NET_VENDOR_RDC=y -CONFIG_R6040=m -CONFIG_NET_VENDOR_SEEQ=y -CONFIG_SEEQ8005=m -CONFIG_NET_VENDOR_SILAN=y -CONFIG_SC92031=m -CONFIG_NET_VENDOR_SIS=y -CONFIG_SIS900=m -CONFIG_SIS190=m -CONFIG_SFC=m -CONFIG_SFC_MTD=y -CONFIG_NET_VENDOR_SMSC=y -CONFIG_PCMCIA_SMC91C92=m -CONFIG_EPIC100=m -CONFIG_SMSC9420=m -CONFIG_NET_VENDOR_STMICRO=y -CONFIG_STMMAC_ETH=m -# CONFIG_STMMAC_DEBUG_FS is not set -# CONFIG_STMMAC_DA is not set -CONFIG_STMMAC_RING=y -# CONFIG_STMMAC_CHAINED is not set -CONFIG_NET_VENDOR_SUN=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNGEM=m -CONFIG_CASSINI=m -CONFIG_NIU=m -CONFIG_NET_VENDOR_TEHUTI=y -CONFIG_TEHUTI=m -CONFIG_NET_VENDOR_TI=y -CONFIG_TLAN=m -CONFIG_NET_VENDOR_VIA=y -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_VIA_VELOCITY=m -CONFIG_NET_VENDOR_XIRCOM=y -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -# CONFIG_DEFXX_MMIO is not set -CONFIG_SKFP=m -CONFIG_HIPPI=y -CONFIG_ROADRUNNER=m -# CONFIG_ROADRUNNER_LARGE_RINGS is not set -CONFIG_NET_SB1000=m -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 -CONFIG_VITESSE_PHY=m -CONFIG_SMSC_PHY=m -CONFIG_BROADCOM_PHY=m -CONFIG_ICPLUS_PHY=m -CONFIG_REALTEK_PHY=m -CONFIG_NATIONAL_PHY=m -CONFIG_STE10XP=m -CONFIG_LSI_ET1011C_PHY=m -CONFIG_MICREL_PHY=m -CONFIG_MDIO_BITBANG=m -CONFIG_MDIO_GPIO=m -CONFIG_PLIP=m -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOATM=m -CONFIG_PPPOE=m -CONFIG_PPTP=m -CONFIG_PPPOL2TP=m -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_SLIP=m -CONFIG_SLHC=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y -# CONFIG_TR is not set - -# -# USB Network Adapters -# -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_USBNET=m -CONFIG_USB_NET_AX8817X=m -CONFIG_USB_NET_CDCETHER=m -CONFIG_USB_NET_CDC_EEM=m -CONFIG_USB_NET_CDC_NCM=m -CONFIG_USB_NET_DM9601=m -CONFIG_USB_NET_SMSC75XX=m -CONFIG_USB_NET_SMSC95XX=m -CONFIG_USB_NET_GL620A=m -CONFIG_USB_NET_NET1080=m -CONFIG_USB_NET_PLUSB=m -CONFIG_USB_NET_MCS7830=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_ARMLINUX=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_KC2190=y -CONFIG_USB_NET_ZAURUS=m -CONFIG_USB_NET_CX82310_ETH=m -CONFIG_USB_NET_KALMIA=m -CONFIG_USB_HSO=m -CONFIG_USB_NET_INT51X1=m -CONFIG_USB_CDC_PHONET=m -CONFIG_USB_IPHETH=m -CONFIG_USB_SIERRA_NET=m -CONFIG_USB_VL600=m -CONFIG_WLAN=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_LIBERTAS_THINFIRM=m -# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set -CONFIG_LIBERTAS_THINFIRM_USB=m -CONFIG_AIRO=m -CONFIG_ATMEL=m -CONFIG_PCI_ATMEL=m -CONFIG_PCMCIA_ATMEL=m -CONFIG_AT76C50X_USB=m -CONFIG_AIRO_CS=m -CONFIG_PCMCIA_WL3501=m -CONFIG_PRISM54=m -CONFIG_USB_ZD1201=m -CONFIG_USB_NET_RNDIS_WLAN=m -CONFIG_RTL8180=m -CONFIG_RTL8187=m -CONFIG_RTL8187_LEDS=y -CONFIG_ADM8211=m -CONFIG_MAC80211_HWSIM=m -CONFIG_MWL8K=m -CONFIG_ATH_COMMON=m -# CONFIG_ATH_DEBUG is not set -CONFIG_ATH5K=m -# CONFIG_ATH5K_DEBUG is not set -CONFIG_ATH5K_PCI=y -CONFIG_ATH9K_HW=m -CONFIG_ATH9K_COMMON=m -CONFIG_ATH9K=m -CONFIG_ATH9K_PCI=y -CONFIG_ATH9K_AHB=y -# CONFIG_ATH9K_DEBUGFS is not set -CONFIG_ATH9K_RATE_CONTROL=y -CONFIG_ATH9K_HTC=m -# CONFIG_ATH9K_HTC_DEBUGFS is not set -CONFIG_CARL9170=m -CONFIG_CARL9170_LEDS=y -CONFIG_CARL9170_WPC=y -CONFIG_CARL9170_HWRNG=y -CONFIG_ATH6KL=m -CONFIG_ATH6KL_DEBUG=y -CONFIG_B43=m -CONFIG_B43_SSB=y -CONFIG_B43_PCI_AUTOSELECT=y -CONFIG_B43_PCICORE_AUTOSELECT=y -CONFIG_B43_PCMCIA=y -CONFIG_B43_SDIO=y -CONFIG_B43_PIO=y -CONFIG_B43_PHY_N=y -CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y -CONFIG_B43_LEDS=y -CONFIG_B43_HWRNG=y -# CONFIG_B43_DEBUG is not set -CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_PCI_AUTOSELECT=y -CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y -CONFIG_B43LEGACY_LEDS=y -CONFIG_B43LEGACY_HWRNG=y -CONFIG_B43LEGACY_DEBUG=y -CONFIG_B43LEGACY_DMA=y -CONFIG_B43LEGACY_PIO=y -CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y -# CONFIG_B43LEGACY_DMA_MODE is not set -# CONFIG_B43LEGACY_PIO_MODE is not set -# CONFIG_BRCMSMAC is not set -# CONFIG_BRCMFMAC is not set -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_IPW2100=m -CONFIG_IPW2100_MONITOR=y -# CONFIG_IPW2100_DEBUG is not set -CONFIG_IPW2200=m -CONFIG_IPW2200_MONITOR=y -CONFIG_IPW2200_RADIOTAP=y -CONFIG_IPW2200_PROMISCUOUS=y -CONFIG_IPW2200_QOS=y -# CONFIG_IPW2200_DEBUG is not set -CONFIG_LIBIPW=m -# CONFIG_LIBIPW_DEBUG is not set -CONFIG_IWLWIFI=m - -# -# Debugging Options -# -# CONFIG_IWLWIFI_DEBUG is not set -# CONFIG_IWLWIFI_DEVICE_SVTOOL is not set -CONFIG_IWLWIFI_LEGACY=m - -# -# Debugging Options -# -# CONFIG_IWLWIFI_LEGACY_DEBUG is not set -CONFIG_IWL4965=m -CONFIG_IWL3945=m -CONFIG_IWM=m -# CONFIG_IWM_DEBUG is not set -CONFIG_LIBERTAS=m -CONFIG_LIBERTAS_USB=m -CONFIG_LIBERTAS_CS=m -CONFIG_LIBERTAS_SDIO=m -CONFIG_LIBERTAS_SPI=m -# CONFIG_LIBERTAS_DEBUG is not set -CONFIG_LIBERTAS_MESH=y -CONFIG_HERMES=m -# CONFIG_HERMES_PRISM is not set -CONFIG_HERMES_CACHE_FW_ON_INIT=y -CONFIG_PLX_HERMES=m -CONFIG_TMD_HERMES=m -CONFIG_NORTEL_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_PCMCIA_SPECTRUM=m -CONFIG_ORINOCO_USB=m -CONFIG_P54_COMMON=m -CONFIG_P54_USB=m -CONFIG_P54_PCI=m -CONFIG_P54_SPI=m -# CONFIG_P54_SPI_DEFAULT_EEPROM is not set -CONFIG_P54_LEDS=y -CONFIG_RT2X00=m -CONFIG_RT2400PCI=m -CONFIG_RT2500PCI=m -CONFIG_RT61PCI=m -CONFIG_RT2800PCI=m -CONFIG_RT2800PCI_RT33XX=y -# CONFIG_RT2800PCI_RT35XX is not set -CONFIG_RT2800PCI_RT53XX=y -CONFIG_RT2500USB=m -CONFIG_RT73USB=m -CONFIG_RT2800USB=m -CONFIG_RT2800USB_RT33XX=y -# CONFIG_RT2800USB_RT35XX is not set -CONFIG_RT2800USB_RT53XX=y -CONFIG_RT2800USB_UNKNOWN=y -CONFIG_RT2800_LIB=m -CONFIG_RT2X00_LIB_PCI=m -CONFIG_RT2X00_LIB_USB=m -CONFIG_RT2X00_LIB=m -CONFIG_RT2X00_LIB_FIRMWARE=y -CONFIG_RT2X00_LIB_CRYPTO=y -CONFIG_RT2X00_LIB_LEDS=y -# CONFIG_RT2X00_DEBUG is not set -CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m -CONFIG_RTL8192DE=m -CONFIG_RTL8192CU=m -CONFIG_RTLWIFI=m -CONFIG_RTL8192C_COMMON=m -CONFIG_WL1251=m -CONFIG_WL1251_SPI=m -CONFIG_WL1251_SDIO=m -CONFIG_WL12XX_MENU=m -CONFIG_WL12XX=m -CONFIG_WL12XX_SPI=m -CONFIG_WL12XX_SDIO=m -CONFIG_WL12XX_SDIO_TEST=m -CONFIG_WL12XX_PLATFORM_DATA=y -CONFIG_ZD1211RW=m -# CONFIG_ZD1211RW_DEBUG is not set -CONFIG_MWIFIEX=m -CONFIG_MWIFIEX_SDIO=m -CONFIG_MWIFIEX_PCIE=m - -# -# WiMAX Wireless Broadband devices -# -CONFIG_WIMAX_I2400M=m -CONFIG_WIMAX_I2400M_USB=m -CONFIG_WIMAX_I2400M_SDIO=m -CONFIG_WIMAX_IWMC3200_SDIO=y -CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 -CONFIG_WAN=y -CONFIG_LANMEDIA=m -CONFIG_HDLC=m -CONFIG_HDLC_RAW=m -CONFIG_HDLC_RAW_ETH=m -CONFIG_HDLC_CISCO=m -CONFIG_HDLC_FR=m -CONFIG_HDLC_PPP=m -CONFIG_HDLC_X25=m -CONFIG_PCI200SYN=m -CONFIG_WANXL=m -# CONFIG_WANXL_BUILD_FIRMWARE is not set -CONFIG_PC300TOO=m -CONFIG_FARSYNC=m -CONFIG_DSCC4=m -CONFIG_DSCC4_PCISYNC=y -CONFIG_DSCC4_PCI_RST=y -CONFIG_DLCI=m -CONFIG_DLCI_MAX=8 -CONFIG_WAN_ROUTER_DRIVERS=m -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -CONFIG_LAPBETHER=m -CONFIG_X25_ASY=m -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y -CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_BACKEND=m -CONFIG_VMXNET3=m -CONFIG_ISDN=y -# CONFIG_ISDN_I4L is not set -CONFIG_ISDN_CAPI=m -# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set -# CONFIG_CAPI_TRACE is not set -CONFIG_ISDN_CAPI_MIDDLEWARE=y -CONFIG_ISDN_CAPI_CAPI20=m - -# -# CAPI hardware drivers -# -CONFIG_CAPI_AVM=y -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -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 -CONFIG_CAPI_EICON=y -CONFIG_ISDN_DIVAS=m -CONFIG_ISDN_DIVAS_BRIPCI=y -CONFIG_ISDN_DIVAS_PRIPCI=y -CONFIG_ISDN_DIVAS_DIVACAPI=m -CONFIG_ISDN_DIVAS_USERIDI=m -CONFIG_ISDN_DIVAS_MAINT=m -CONFIG_ISDN_DRV_GIGASET=m -CONFIG_GIGASET_CAPI=y -# CONFIG_GIGASET_DUMMYLL is not set -CONFIG_GIGASET_BASE=m -CONFIG_GIGASET_M105=m -CONFIG_GIGASET_M101=m -# CONFIG_GIGASET_DEBUG is not set -CONFIG_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_MISDN=m -CONFIG_MISDN_DSP=m -CONFIG_MISDN_L1OIP=m - -# -# mISDN hardware drivers -# -CONFIG_MISDN_HFCPCI=m -CONFIG_MISDN_HFCMULTI=m -CONFIG_MISDN_HFCUSB=m -CONFIG_MISDN_AVMFRITZ=m -# CONFIG_MISDN_SPEEDFAX is not set -# CONFIG_MISDN_INFINEON is not set -# CONFIG_MISDN_W6692 is not set -# CONFIG_MISDN_NETJET is not set -CONFIG_MISDN_IPAC=m -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -CONFIG_INPUT_FF_MEMLESS=m -CONFIG_INPUT_POLLDEV=m -CONFIG_INPUT_SPARSEKMAP=m - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_EVBUG=m - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -# CONFIG_KEYBOARD_ADP5589 is not set -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_QT1070 is not set -# CONFIG_KEYBOARD_QT2160 is not set -CONFIG_KEYBOARD_LKKBD=m -CONFIG_KEYBOARD_GPIO=m -CONFIG_KEYBOARD_GPIO_POLLED=m -CONFIG_KEYBOARD_TCA6416=m -CONFIG_KEYBOARD_MATRIX=m -CONFIG_KEYBOARD_LM8323=m -# CONFIG_KEYBOARD_MAX7359 is not set -CONFIG_KEYBOARD_MCS=m -# CONFIG_KEYBOARD_MPR121 is not set -CONFIG_KEYBOARD_NEWTON=m -# CONFIG_KEYBOARD_OPENCORES is not set -CONFIG_KEYBOARD_STOWAWAY=m -CONFIG_KEYBOARD_SUNKBD=m -CONFIG_KEYBOARD_XTKBD=m -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -# CONFIG_MOUSE_PS2_SENTELIC is not set -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -CONFIG_MOUSE_SERIAL=m -CONFIG_MOUSE_APPLETOUCH=m -CONFIG_MOUSE_BCM5974=m -CONFIG_MOUSE_VSXXXAA=m -CONFIG_MOUSE_GPIO=m -CONFIG_MOUSE_SYNAPTICS_I2C=m -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=m -CONFIG_TOUCHSCREEN_AD7877=m -CONFIG_TOUCHSCREEN_AD7879=m -CONFIG_TOUCHSCREEN_AD7879_I2C=m -CONFIG_TOUCHSCREEN_AD7879_SPI=m -CONFIG_TOUCHSCREEN_ATMEL_MXT=m -CONFIG_TOUCHSCREEN_BU21013=m -CONFIG_TOUCHSCREEN_CY8CTMG110=m -CONFIG_TOUCHSCREEN_DYNAPRO=m -CONFIG_TOUCHSCREEN_HAMPSHIRE=m -CONFIG_TOUCHSCREEN_EETI=m -CONFIG_TOUCHSCREEN_FUJITSU=m -CONFIG_TOUCHSCREEN_GUNZE=m -CONFIG_TOUCHSCREEN_ELO=m -CONFIG_TOUCHSCREEN_WACOM_W8001=m -# CONFIG_TOUCHSCREEN_MAX11801 is not set -# CONFIG_TOUCHSCREEN_MCS5000 is not set -CONFIG_TOUCHSCREEN_MTOUCH=m -CONFIG_TOUCHSCREEN_INEXIO=m -CONFIG_TOUCHSCREEN_MK712=m -CONFIG_TOUCHSCREEN_PENMOUNT=m -CONFIG_TOUCHSCREEN_TOUCHRIGHT=m -CONFIG_TOUCHSCREEN_TOUCHWIN=m -CONFIG_TOUCHSCREEN_UCB1400=m -CONFIG_TOUCHSCREEN_WM97XX=m -CONFIG_TOUCHSCREEN_WM9705=y -CONFIG_TOUCHSCREEN_WM9712=y -CONFIG_TOUCHSCREEN_WM9713=y -CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -# CONFIG_TOUCHSCREEN_MC13783 is not set -CONFIG_TOUCHSCREEN_USB_EGALAX=y -CONFIG_TOUCHSCREEN_USB_PANJIT=y -CONFIG_TOUCHSCREEN_USB_3M=y -CONFIG_TOUCHSCREEN_USB_ITM=y -CONFIG_TOUCHSCREEN_USB_ETURBO=y -CONFIG_TOUCHSCREEN_USB_GUNZE=y -CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y -CONFIG_TOUCHSCREEN_USB_IRTOUCH=y -CONFIG_TOUCHSCREEN_USB_IDEALTEK=y -CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y -CONFIG_TOUCHSCREEN_USB_GOTOP=y -CONFIG_TOUCHSCREEN_USB_JASTEC=y -CONFIG_TOUCHSCREEN_USB_E2I=y -CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y -CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y -CONFIG_TOUCHSCREEN_USB_NEXIO=y -CONFIG_TOUCHSCREEN_TOUCHIT213=m -CONFIG_TOUCHSCREEN_TSC_SERIO=m -# CONFIG_TOUCHSCREEN_TSC2005 is not set -CONFIG_TOUCHSCREEN_TSC2007=m -CONFIG_TOUCHSCREEN_ST1232=m -CONFIG_TOUCHSCREEN_TPS6507X=m -CONFIG_INPUT_MISC=y -CONFIG_INPUT_AD714X=m -CONFIG_INPUT_AD714X_I2C=m -CONFIG_INPUT_AD714X_SPI=m -# CONFIG_INPUT_BMA150 is not set -CONFIG_INPUT_PCSPKR=m -# CONFIG_INPUT_MC13783_PWRBUTTON is not set -CONFIG_INPUT_MMA8450=m -CONFIG_INPUT_MPU3050=m -CONFIG_INPUT_APANEL=m -CONFIG_INPUT_ATLAS_BTNS=m -CONFIG_INPUT_ATI_REMOTE2=m -CONFIG_INPUT_KEYSPAN_REMOTE=m -CONFIG_INPUT_KXTJ9=m -# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set -CONFIG_INPUT_POWERMATE=m -CONFIG_INPUT_YEALINK=m -CONFIG_INPUT_CM109=m -CONFIG_INPUT_UINPUT=m -CONFIG_INPUT_PCF50633_PMU=m -CONFIG_INPUT_PCF8574=m -CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -CONFIG_INPUT_ADXL34X=m -CONFIG_INPUT_ADXL34X_I2C=m -CONFIG_INPUT_ADXL34X_SPI=m -CONFIG_INPUT_CMA3000=m -CONFIG_INPUT_CMA3000_I2C=m -CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=m -CONFIG_SERIO_CT82C710=m -CONFIG_SERIO_PARKBD=m -CONFIG_SERIO_PCIPS2=m -CONFIG_SERIO_LIBPS2=y -CONFIG_SERIO_RAW=m -CONFIG_SERIO_ALTERA_PS2=m -CONFIG_SERIO_PS2MULT=m -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_UNIX98_PTYS=y -CONFIG_DEVPTS_MULTIPLE_INSTANCES=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_SYNCLINK=m -CONFIG_SYNCLINKMP=m -CONFIG_SYNCLINK_GT=m -CONFIG_NOZOMI=m -CONFIG_ISI=m -CONFIG_N_HDLC=m -# CONFIG_N_GSM is not set -# CONFIG_TRACE_SINK is not set -# CONFIG_DEVKMEM is not set -CONFIG_STALDRV=y - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_PNP=y -CONFIG_SERIAL_8250_CS=m -CONFIG_SERIAL_8250_NR_UARTS=16 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -CONFIG_SERIAL_8250_RSA=y - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_MAX3100=m -CONFIG_SERIAL_MAX3107=m -CONFIG_SERIAL_MRST_MAX3110=m -CONFIG_SERIAL_MFD_HSU=m -CONFIG_SERIAL_UARTLITE=m -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_SERIAL_JSM=m -CONFIG_SERIAL_TIMBERDALE=m -CONFIG_SERIAL_ALTERA_JTAGUART=m -CONFIG_SERIAL_ALTERA_UART=m -CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4 -CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200 -CONFIG_SERIAL_IFX6X60=m -CONFIG_SERIAL_PCH_UART=m -# CONFIG_SERIAL_XILINX_PS_UART is not set -# CONFIG_TTY_PRINTK is not set -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=m -CONFIG_HVC_DRIVER=y -CONFIG_HVC_IRQ=y -CONFIG_HVC_XEN=y -CONFIG_VIRTIO_CONSOLE=m -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m -CONFIG_HW_RANDOM=m -CONFIG_HW_RANDOM_TIMERIOMEM=m -CONFIG_HW_RANDOM_INTEL=m -CONFIG_HW_RANDOM_AMD=m -CONFIG_HW_RANDOM_VIA=m -CONFIG_HW_RANDOM_VIRTIO=m -CONFIG_NVRAM=m -CONFIG_R3964=m -CONFIG_APPLICOM=m - -# -# PCMCIA character devices -# -CONFIG_SYNCLINK_CS=m -CONFIG_CARDMAN_4000=m -CONFIG_CARDMAN_4040=m -CONFIG_IPWIRELESS=m -CONFIG_MWAVE=m -CONFIG_RAW_DRIVER=m -CONFIG_MAX_RAW_DEVS=256 -CONFIG_HPET=y -CONFIG_HPET_MMAP=y -CONFIG_HANGCHECK_TIMER=m -CONFIG_TCG_TPM=m -CONFIG_TCG_TIS=m -CONFIG_TCG_NSC=m -CONFIG_TCG_ATMEL=m -CONFIG_TCG_INFINEON=m -CONFIG_TELCLOCK=m -CONFIG_DEVPORT=y -CONFIG_RAMOOPS=m -CONFIG_I2C=m -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_MUX=m - -# -# Multiplexer I2C Chip support -# -CONFIG_I2C_MUX_GPIO=m -CONFIG_I2C_MUX_PCA9541=m -CONFIG_I2C_MUX_PCA954x=m -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_SMBUS=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_ALGOPCA=m - -# -# I2C Hardware Bus support -# - -# -# PC SMBus host controller drivers -# -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_ISCH=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_NFORCE2=m -CONFIG_I2C_NFORCE2_S4985=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m -CONFIG_I2C_SIS96X=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m - -# -# ACPI drivers -# -CONFIG_I2C_SCMI=m - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -# CONFIG_I2C_DESIGNWARE_PCI is not set -CONFIG_I2C_GPIO=m -CONFIG_I2C_INTEL_MID=m -CONFIG_I2C_OCORES=m -CONFIG_I2C_PCA_PLATFORM=m -# CONFIG_I2C_PXA_PCI is not set -CONFIG_I2C_SIMTEC=m -CONFIG_I2C_XILINX=m -CONFIG_I2C_EG20T=m - -# -# External I2C/SMBus adapter drivers -# -CONFIG_I2C_DIOLAN_U2C=m -CONFIG_I2C_PARPORT=m -CONFIG_I2C_PARPORT_LIGHT=m -CONFIG_I2C_TAOS_EVM=m -CONFIG_I2C_TINY_USB=m - -# -# Other I2C/SMBus bus drivers -# -CONFIG_I2C_STUB=m -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -# CONFIG_SPI_ALTERA is not set -CONFIG_SPI_BITBANG=m -CONFIG_SPI_BUTTERFLY=m -CONFIG_SPI_GPIO=m -CONFIG_SPI_LM70_LLP=m -# CONFIG_SPI_OC_TINY is not set -# CONFIG_SPI_PXA2XX_PCI is not set -CONFIG_SPI_TOPCLIFF_PCH=m -# CONFIG_SPI_XILINX is not set -CONFIG_SPI_DESIGNWARE=m -CONFIG_SPI_DW_PCI=m - -# -# SPI Protocol Masters -# -CONFIG_SPI_SPIDEV=m -CONFIG_SPI_TLE62X0=m - -# -# PPS support -# -# CONFIG_PPS is not set - -# -# PPS generators support -# - -# -# PTP clock support -# - -# -# Enable Device Drivers -> PPS to see the PTP clock options. -# -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -# CONFIG_GPIO_SYSFS is not set -CONFIG_GPIO_MAX730X=m - -# -# Memory mapped GPIO drivers: -# -# CONFIG_GPIO_GENERIC_PLATFORM is not set -CONFIG_GPIO_IT8761E=m -CONFIG_GPIO_SCH=m -CONFIG_GPIO_VX855=m - -# -# I2C GPIO expanders: -# -CONFIG_GPIO_MAX7300=m -CONFIG_GPIO_MAX732X=m -CONFIG_GPIO_PCA953X=m -CONFIG_GPIO_PCF857X=m -CONFIG_GPIO_ADP5588=m - -# -# PCI GPIO expanders: -# -CONFIG_GPIO_CS5535=m -# CONFIG_GPIO_LANGWELL is not set -CONFIG_GPIO_PCH=m -CONFIG_GPIO_ML_IOH=m -CONFIG_GPIO_TIMBERDALE=y -CONFIG_GPIO_RDC321X=m - -# -# SPI GPIO expanders: -# -CONFIG_GPIO_MAX7301=m -CONFIG_GPIO_MCP23S08=m -# CONFIG_GPIO_MC33880 is not set -CONFIG_GPIO_74X164=m - -# -# AC97 GPIO expanders: -# -# CONFIG_GPIO_UCB1400 is not set - -# -# MODULbus GPIO expanders: -# -CONFIG_GPIO_JANZ_TTL=m -# CONFIG_W1 is not set -CONFIG_POWER_SUPPLY=m -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_TEST_POWER is not set -# CONFIG_BATTERY_DS2780 is not set -# CONFIG_BATTERY_DS2782 is not set -# CONFIG_BATTERY_BQ20Z75 is not set -# CONFIG_BATTERY_BQ27x00 is not set -# CONFIG_BATTERY_MAX17040 is not set -# CONFIG_BATTERY_MAX17042 is not set -# CONFIG_CHARGER_PCF50633 is not set -# CONFIG_CHARGER_ISP1704 is not set -# CONFIG_CHARGER_MAX8903 is not set -# CONFIG_CHARGER_GPIO is not set -CONFIG_HWMON=m -CONFIG_HWMON_VID=m -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Native drivers -# -CONFIG_SENSORS_ABITUGURU=m -CONFIG_SENSORS_ABITUGURU3=m -CONFIG_SENSORS_AD7314=m -CONFIG_SENSORS_AD7414=m -CONFIG_SENSORS_AD7418=m -CONFIG_SENSORS_ADCXX=m -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM1029=m -CONFIG_SENSORS_ADM1031=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_ADT7411=m -CONFIG_SENSORS_ADT7462=m -CONFIG_SENSORS_ADT7470=m -CONFIG_SENSORS_ADT7475=m -CONFIG_SENSORS_ASC7621=m -CONFIG_SENSORS_K8TEMP=m -CONFIG_SENSORS_K10TEMP=m -CONFIG_SENSORS_FAM15H_POWER=m -CONFIG_SENSORS_ASB100=m -CONFIG_SENSORS_ATXP1=m -CONFIG_SENSORS_DS620=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_I5K_AMB=m -CONFIG_SENSORS_F71805F=m -CONFIG_SENSORS_F71882FG=m -CONFIG_SENSORS_F75375S=m -CONFIG_SENSORS_FSCHMD=m -CONFIG_SENSORS_G760A=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_GPIO_FAN=m -CONFIG_SENSORS_CORETEMP=m -CONFIG_SENSORS_IBMAEM=m -CONFIG_SENSORS_IBMPEX=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_JC42=m -CONFIG_SENSORS_LINEAGE=m -CONFIG_SENSORS_LM63=m -CONFIG_SENSORS_LM70=m -CONFIG_SENSORS_LM73=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_LM93=m -CONFIG_SENSORS_LTC4151=m -CONFIG_SENSORS_LTC4215=m -CONFIG_SENSORS_LTC4245=m -CONFIG_SENSORS_LTC4261=m -CONFIG_SENSORS_LM95241=m -CONFIG_SENSORS_LM95245=m -CONFIG_SENSORS_MAX1111=m -CONFIG_SENSORS_MAX16065=m -CONFIG_SENSORS_MAX1619=m -CONFIG_SENSORS_MAX1668=m -CONFIG_SENSORS_MAX6639=m -CONFIG_SENSORS_MAX6642=m -CONFIG_SENSORS_MAX6650=m -CONFIG_SENSORS_NTC_THERMISTOR=m -CONFIG_SENSORS_PC87360=m -CONFIG_SENSORS_PC87427=m -CONFIG_SENSORS_PCF8591=m -CONFIG_PMBUS=m -CONFIG_SENSORS_PMBUS=m -CONFIG_SENSORS_ADM1275=m -CONFIG_SENSORS_LM25066=m -CONFIG_SENSORS_LTC2978=m -CONFIG_SENSORS_MAX16064=m -CONFIG_SENSORS_MAX34440=m -CONFIG_SENSORS_MAX8688=m -CONFIG_SENSORS_UCD9000=m -CONFIG_SENSORS_UCD9200=m -CONFIG_SENSORS_ZL6100=m -CONFIG_SENSORS_SHT15=m -CONFIG_SENSORS_SHT21=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMM665=m -CONFIG_SENSORS_DME1737=m -CONFIG_SENSORS_EMC1403=m -CONFIG_SENSORS_EMC2103=m -CONFIG_SENSORS_EMC6W201=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_SMSC47M192=m -CONFIG_SENSORS_SMSC47B397=m -CONFIG_SENSORS_SCH56XX_COMMON=m -CONFIG_SENSORS_SCH5627=m -CONFIG_SENSORS_SCH5636=m -CONFIG_SENSORS_ADS1015=m -CONFIG_SENSORS_ADS7828=m -CONFIG_SENSORS_ADS7871=m -CONFIG_SENSORS_AMC6821=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_TMP102=m -CONFIG_SENSORS_TMP401=m -CONFIG_SENSORS_TMP421=m -CONFIG_SENSORS_VIA_CPUTEMP=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_W83791D=m -CONFIG_SENSORS_W83792D=m -CONFIG_SENSORS_W83793=m -CONFIG_SENSORS_W83795=m -CONFIG_SENSORS_W83795_FANCTRL=y -CONFIG_SENSORS_W83L785TS=m -CONFIG_SENSORS_W83L786NG=m -CONFIG_SENSORS_W83627HF=m -CONFIG_SENSORS_W83627EHF=m -CONFIG_SENSORS_APPLESMC=m -# CONFIG_SENSORS_MC13783_ADC is not set - -# -# ACPI drivers -# -CONFIG_SENSORS_ACPI_POWER=m -CONFIG_SENSORS_ATK0110=m -CONFIG_THERMAL=y -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -CONFIG_SOFT_WATCHDOG=m -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_F71808E_WDT=m -CONFIG_SP5100_TCO=m -CONFIG_GEODE_WDT=m -CONFIG_SC520_WDT=m -# CONFIG_SBC_FITPC2_WATCHDOG is not set -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_IBMASR=m -CONFIG_WAFER_WDT=m -CONFIG_I6300ESB_WDT=m -CONFIG_ITCO_WDT=m -CONFIG_ITCO_VENDOR_SUPPORT=y -CONFIG_IT8712F_WDT=m -CONFIG_IT87_WDT=m -# CONFIG_HP_WATCHDOG is not set -CONFIG_SC1200_WDT=m -CONFIG_PC87413_WDT=m -CONFIG_NV_TCO=m -CONFIG_60XX_WDT=m -CONFIG_SBC8360_WDT=m -CONFIG_CPU5_WDT=m -CONFIG_SMSC_SCH311X_WDT=m -CONFIG_SMSC37B787_WDT=m -CONFIG_W83627HF_WDT=m -CONFIG_W83697HF_WDT=m -CONFIG_W83697UG_WDT=m -CONFIG_W83877F_WDT=m -CONFIG_W83977F_WDT=m -CONFIG_MACHZ_WDT=m -CONFIG_SBC_EPX_C3_WATCHDOG=m -CONFIG_XEN_WDT=m - -# -# PCI-based Watchdog Cards -# -CONFIG_PCIPCWATCHDOG=m -CONFIG_WDTPCI=m - -# -# USB-based Watchdog Cards -# -CONFIG_USBPCWATCHDOG=m -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -CONFIG_SSB=m -CONFIG_SSB_SPROM=y -CONFIG_SSB_BLOCKIO=y -CONFIG_SSB_PCIHOST_POSSIBLE=y -CONFIG_SSB_PCIHOST=y -CONFIG_SSB_B43_PCI_BRIDGE=y -CONFIG_SSB_PCMCIAHOST_POSSIBLE=y -CONFIG_SSB_PCMCIAHOST=y -CONFIG_SSB_SDIOHOST_POSSIBLE=y -CONFIG_SSB_SDIOHOST=y -# CONFIG_SSB_SILENT is not set -# CONFIG_SSB_DEBUG is not set -CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y -CONFIG_SSB_DRIVER_PCICORE=y -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -CONFIG_MFD_CORE=m -CONFIG_MFD_SM501=m -# CONFIG_MFD_SM501_GPIO is not set -CONFIG_HTC_PASIC3=m -CONFIG_UCB1400_CORE=m -# CONFIG_TPS6105X is not set -CONFIG_TPS65010=m -CONFIG_TPS6507X=m -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_MFD_TMIO is not set -CONFIG_MFD_WM8400=m -# CONFIG_MFD_WM831X_SPI is not set -CONFIG_MFD_PCF50633=m -CONFIG_PCF50633_ADC=m -CONFIG_PCF50633_GPIO=m -CONFIG_MFD_MC13783=m -CONFIG_MFD_MC13XXX=m -CONFIG_ABX500_CORE=y -# CONFIG_EZX_PCAP is not set -# CONFIG_AB8500_CORE is not set -CONFIG_MFD_CS5535=m -CONFIG_MFD_TIMBERDALE=m -CONFIG_LPC_SCH=m -CONFIG_MFD_RDC321X=m -CONFIG_MFD_JANZ_CMODIO=m -CONFIG_MFD_VX855=m -CONFIG_MFD_WL1273_CORE=m -# CONFIG_REGULATOR is not set -CONFIG_MEDIA_SUPPORT=m - -# -# Multimedia core support -# -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_DEV=m -CONFIG_VIDEO_V4L2_COMMON=m -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_DVB_CORE=m -CONFIG_DVB_NET=y -CONFIG_VIDEO_MEDIA=m - -# -# Multimedia drivers -# -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_RC_CORE=m -CONFIG_LIRC=m -CONFIG_RC_MAP=m -CONFIG_IR_NEC_DECODER=m -CONFIG_IR_RC5_DECODER=m -CONFIG_IR_RC6_DECODER=m -CONFIG_IR_JVC_DECODER=m -CONFIG_IR_SONY_DECODER=m -CONFIG_IR_RC5_SZ_DECODER=m -CONFIG_IR_MCE_KBD_DECODER=m -CONFIG_IR_LIRC_CODEC=m -CONFIG_RC_ATI_REMOTE=m -# CONFIG_IR_ENE is not set -CONFIG_IR_IMON=m -# CONFIG_IR_MCEUSB is not set -CONFIG_IR_ITE_CIR=m -CONFIG_IR_FINTEK=m -# CONFIG_IR_NUVOTON is not set -CONFIG_IR_REDRAT3=m -# CONFIG_IR_STREAMZAP is not set -CONFIG_IR_WINBOND_CIR=m -CONFIG_RC_LOOPBACK=m -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=m -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=m -CONFIG_MEDIA_TUNER_TDA8290=m -CONFIG_MEDIA_TUNER_TDA827X=m -CONFIG_MEDIA_TUNER_TDA18271=m -CONFIG_MEDIA_TUNER_TDA9887=m -CONFIG_MEDIA_TUNER_TEA5761=m -CONFIG_MEDIA_TUNER_TEA5767=m -CONFIG_MEDIA_TUNER_MT20XX=m -CONFIG_MEDIA_TUNER_MT2060=m -CONFIG_MEDIA_TUNER_MT2266=m -CONFIG_MEDIA_TUNER_MT2131=m -CONFIG_MEDIA_TUNER_QT1010=m -CONFIG_MEDIA_TUNER_XC2028=m -CONFIG_MEDIA_TUNER_XC5000=m -CONFIG_MEDIA_TUNER_XC4000=m -CONFIG_MEDIA_TUNER_MXL5005S=m -CONFIG_MEDIA_TUNER_MXL5007T=m -CONFIG_MEDIA_TUNER_MC44S803=m -CONFIG_MEDIA_TUNER_MAX2165=m -CONFIG_MEDIA_TUNER_TDA18218=m -CONFIG_MEDIA_TUNER_TDA18212=m -CONFIG_VIDEO_V4L2=m -CONFIG_VIDEOBUF_GEN=m -CONFIG_VIDEOBUF_DMA_SG=m -CONFIG_VIDEOBUF_VMALLOC=m -CONFIG_VIDEOBUF_DMA_CONTIG=m -CONFIG_VIDEOBUF_DVB=m -CONFIG_VIDEO_BTCX=m -CONFIG_VIDEO_TVEEPROM=m -CONFIG_VIDEO_TUNER=m -CONFIG_V4L2_MEM2MEM_DEV=m -CONFIG_VIDEOBUF2_CORE=m -CONFIG_VIDEOBUF2_MEMOPS=m -CONFIG_VIDEOBUF2_DMA_CONTIG=m -CONFIG_VIDEOBUF2_VMALLOC=m -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set -CONFIG_VIDEO_IR_I2C=m - -# -# Encoders, decoders, sensors and other helper chips -# - -# -# Audio decoders, processors and mixers -# -CONFIG_VIDEO_TVAUDIO=m -CONFIG_VIDEO_TDA7432=m -CONFIG_VIDEO_TDA9840=m -CONFIG_VIDEO_TEA6415C=m -CONFIG_VIDEO_TEA6420=m -CONFIG_VIDEO_MSP3400=m -CONFIG_VIDEO_CS5345=m -CONFIG_VIDEO_CS53L32A=m -CONFIG_VIDEO_TLV320AIC23B=m -CONFIG_VIDEO_WM8775=m -CONFIG_VIDEO_WM8739=m -CONFIG_VIDEO_VP27SMPX=m - -# -# RDS decoders -# -CONFIG_VIDEO_SAA6588=m - -# -# Video decoders -# -CONFIG_VIDEO_ADV7180=m -CONFIG_VIDEO_BT819=m -CONFIG_VIDEO_BT856=m -CONFIG_VIDEO_BT866=m -CONFIG_VIDEO_KS0127=m -CONFIG_VIDEO_SAA7110=m -CONFIG_VIDEO_SAA711X=m -CONFIG_VIDEO_SAA7191=m -CONFIG_VIDEO_TVP514X=m -CONFIG_VIDEO_TVP5150=m -CONFIG_VIDEO_TVP7002=m -CONFIG_VIDEO_VPX3220=m - -# -# Video and audio decoders -# -CONFIG_VIDEO_SAA717X=m -CONFIG_VIDEO_CX25840=m - -# -# MPEG video encoders -# -CONFIG_VIDEO_CX2341X=m - -# -# Video encoders -# -CONFIG_VIDEO_SAA7127=m -CONFIG_VIDEO_SAA7185=m -CONFIG_VIDEO_ADV7170=m -CONFIG_VIDEO_ADV7175=m -CONFIG_VIDEO_ADV7343=m -CONFIG_VIDEO_AK881X=m - -# -# Camera sensor devices -# -CONFIG_VIDEO_OV7670=m -CONFIG_VIDEO_MT9P031=m -CONFIG_VIDEO_MT9T001=m -CONFIG_VIDEO_MT9V011=m -CONFIG_VIDEO_MT9V032=m -CONFIG_VIDEO_TCM825X=m -# CONFIG_VIDEO_SR030PC30 is not set -CONFIG_VIDEO_NOON010PC30=m -# CONFIG_VIDEO_M5MOLS is not set -CONFIG_VIDEO_S5K6AA=m - -# -# Flash devices -# -# CONFIG_VIDEO_ADP1653 is not set - -# -# Video improvement chips -# -CONFIG_VIDEO_UPD64031A=m -CONFIG_VIDEO_UPD64083=m - -# -# Miscelaneous helper chips -# -CONFIG_VIDEO_THS7303=m -CONFIG_VIDEO_M52790=m -# CONFIG_VIDEO_VIVI is not set -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_BT848_DVB=y -CONFIG_VIDEO_BWQCAM=m -CONFIG_VIDEO_CQCAM=m -# CONFIG_VIDEO_CPIA2 is not set -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_DC30=m -CONFIG_VIDEO_ZORAN_ZR36060=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZORAN_LML33R10=m -CONFIG_VIDEO_ZORAN_AVS6EYES=m -CONFIG_VIDEO_MEYE=m -CONFIG_VIDEO_SAA7134=m -CONFIG_VIDEO_SAA7134_ALSA=m -CONFIG_VIDEO_SAA7134_RC=y -CONFIG_VIDEO_SAA7134_DVB=m -CONFIG_VIDEO_MXB=m -CONFIG_VIDEO_HEXIUM_ORION=m -CONFIG_VIDEO_HEXIUM_GEMINI=m -CONFIG_VIDEO_TIMBERDALE=m -CONFIG_VIDEO_CX88=m -CONFIG_VIDEO_CX88_ALSA=m -CONFIG_VIDEO_CX88_BLACKBIRD=m -CONFIG_VIDEO_CX88_DVB=m -CONFIG_VIDEO_CX88_MPEG=m -CONFIG_VIDEO_CX88_VP3054=m -CONFIG_VIDEO_CX23885=m -# CONFIG_MEDIA_ALTERA_CI is not set -# CONFIG_VIDEO_CX25821 is not set -CONFIG_VIDEO_AU0828=m -CONFIG_VIDEO_IVTV=m -CONFIG_VIDEO_FB_IVTV=m -CONFIG_VIDEO_CX18=m -CONFIG_VIDEO_CX18_ALSA=m -CONFIG_VIDEO_SAA7164=m -CONFIG_VIDEO_CAFE_CCIC=m -# CONFIG_VIDEO_VIA_CAMERA is not set -CONFIG_SOC_CAMERA=m -# CONFIG_SOC_CAMERA_IMX074 is not set -CONFIG_SOC_CAMERA_MT9M001=m -CONFIG_SOC_CAMERA_MT9M111=m -CONFIG_SOC_CAMERA_MT9T031=m -CONFIG_SOC_CAMERA_MT9T112=m -CONFIG_SOC_CAMERA_MT9V022=m -CONFIG_SOC_CAMERA_RJ54N1=m -CONFIG_SOC_CAMERA_TW9910=m -CONFIG_SOC_CAMERA_PLATFORM=m -CONFIG_SOC_CAMERA_OV2640=m -# CONFIG_SOC_CAMERA_OV5642 is not set -# CONFIG_SOC_CAMERA_OV6650 is not set -CONFIG_SOC_CAMERA_OV772X=m -CONFIG_SOC_CAMERA_OV9640=m -CONFIG_SOC_CAMERA_OV9740=m -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=m -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=m -CONFIG_USB_M5602=m -CONFIG_USB_STV06XX=m -CONFIG_USB_GL860=m -CONFIG_USB_GSPCA_BENQ=m -CONFIG_USB_GSPCA_CONEX=m -CONFIG_USB_GSPCA_CPIA1=m -CONFIG_USB_GSPCA_ETOMS=m -CONFIG_USB_GSPCA_FINEPIX=m -CONFIG_USB_GSPCA_JEILINJ=m -CONFIG_USB_GSPCA_KINECT=m -# CONFIG_USB_GSPCA_KONICA is not set -CONFIG_USB_GSPCA_MARS=m -CONFIG_USB_GSPCA_MR97310A=m -CONFIG_USB_GSPCA_NW80X=m -CONFIG_USB_GSPCA_OV519=m -CONFIG_USB_GSPCA_OV534=m -CONFIG_USB_GSPCA_OV534_9=m -CONFIG_USB_GSPCA_PAC207=m -CONFIG_USB_GSPCA_PAC7302=m -CONFIG_USB_GSPCA_PAC7311=m -CONFIG_USB_GSPCA_SE401=m -CONFIG_USB_GSPCA_SN9C2028=m -CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SONIXB=m -CONFIG_USB_GSPCA_SONIXJ=m -CONFIG_USB_GSPCA_SPCA500=m -CONFIG_USB_GSPCA_SPCA501=m -CONFIG_USB_GSPCA_SPCA505=m -CONFIG_USB_GSPCA_SPCA506=m -CONFIG_USB_GSPCA_SPCA508=m -CONFIG_USB_GSPCA_SPCA561=m -# CONFIG_USB_GSPCA_SPCA1528 is not set -CONFIG_USB_GSPCA_SQ905=m -CONFIG_USB_GSPCA_SQ905C=m -# CONFIG_USB_GSPCA_SQ930X is not set -CONFIG_USB_GSPCA_STK014=m -CONFIG_USB_GSPCA_STV0680=m -CONFIG_USB_GSPCA_SUNPLUS=m -CONFIG_USB_GSPCA_T613=m -CONFIG_USB_GSPCA_TOPRO=m -CONFIG_USB_GSPCA_TV8532=m -CONFIG_USB_GSPCA_VC032X=m -CONFIG_USB_GSPCA_VICAM=m -# CONFIG_USB_GSPCA_XIRLINK_CIT is not set -CONFIG_USB_GSPCA_ZC3XX=m -CONFIG_VIDEO_PVRUSB2=m -CONFIG_VIDEO_PVRUSB2_SYSFS=y -CONFIG_VIDEO_PVRUSB2_DVB=y -# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set -CONFIG_VIDEO_HDPVR=m -CONFIG_VIDEO_EM28XX=m -CONFIG_VIDEO_EM28XX_ALSA=m -CONFIG_VIDEO_EM28XX_DVB=m -CONFIG_VIDEO_EM28XX_RC=y -CONFIG_VIDEO_TLG2300=m -CONFIG_VIDEO_CX231XX=m -CONFIG_VIDEO_CX231XX_RC=y -CONFIG_VIDEO_CX231XX_ALSA=m -CONFIG_VIDEO_CX231XX_DVB=m -# CONFIG_VIDEO_TM6000 is not set -CONFIG_VIDEO_USBVISION=m -CONFIG_USB_ET61X251=m -CONFIG_USB_SN9C102=m -# CONFIG_USB_PWC is not set -CONFIG_USB_ZR364XX=m -CONFIG_USB_STKWEBCAM=m -CONFIG_USB_S2255=m -CONFIG_V4L_MEM2MEM_DRIVERS=y -CONFIG_VIDEO_MEM2MEM_TESTDEV=m -CONFIG_RADIO_ADAPTERS=y -CONFIG_RADIO_MAXIRADIO=m -# CONFIG_I2C_SI4713 is not set -# CONFIG_RADIO_SI4713 is not set -CONFIG_USB_DSBR=m -# CONFIG_RADIO_SI470X is not set -CONFIG_USB_MR800=m -CONFIG_RADIO_TEA5764=m -CONFIG_RADIO_SAA7706H=m -CONFIG_RADIO_TEF6862=m -CONFIG_RADIO_TIMBERDALE=m -CONFIG_RADIO_WL1273=m - -# -# Texas Instruments WL128x FM driver (ST based) -# -CONFIG_RADIO_WL128X=m -CONFIG_DVB_MAX_ADAPTERS=8 -# CONFIG_DVB_DYNAMIC_MINORS is not set -CONFIG_DVB_CAPTURE_DRIVERS=y - -# -# Supported SAA7146 based PCI Adapters -# -CONFIG_TTPCI_EEPROM=m -CONFIG_DVB_AV7110=m -CONFIG_DVB_AV7110_OSD=y -CONFIG_DVB_BUDGET_CORE=m -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_DIB0700=m -CONFIG_DVB_USB_UMT_010=m -CONFIG_DVB_USB_CXUSB=m -CONFIG_DVB_USB_M920X=m -CONFIG_DVB_USB_GL861=m -CONFIG_DVB_USB_AU6610=m -CONFIG_DVB_USB_DIGITV=m -CONFIG_DVB_USB_VP7045=m -CONFIG_DVB_USB_VP702X=m -CONFIG_DVB_USB_GP8PSK=m -CONFIG_DVB_USB_NOVA_T_USB2=m -CONFIG_DVB_USB_TTUSB2=m -CONFIG_DVB_USB_DTT200U=m -CONFIG_DVB_USB_OPERA1=m -CONFIG_DVB_USB_AF9005=m -CONFIG_DVB_USB_AF9005_REMOTE=m -CONFIG_DVB_USB_PCTV452E=m -CONFIG_DVB_USB_DW2102=m -CONFIG_DVB_USB_CINERGY_T2=m -CONFIG_DVB_USB_ANYSEE=m -CONFIG_DVB_USB_DTV5100=m -CONFIG_DVB_USB_AF9015=m -CONFIG_DVB_USB_CE6230=m -# CONFIG_DVB_USB_FRIIO is not set -CONFIG_DVB_USB_EC168=m -CONFIG_DVB_USB_AZ6027=m -# CONFIG_DVB_USB_LME2510 is not set -CONFIG_DVB_USB_TECHNISAT_USB2=m -CONFIG_DVB_USB_IT913X=m -CONFIG_DVB_USB_MXL111SF=m -CONFIG_DVB_TTUSB_BUDGET=m -CONFIG_DVB_TTUSB_DEC=m -CONFIG_SMS_SIANO_MDTV=m - -# -# Siano module components -# -CONFIG_SMS_USB_DRV=m -CONFIG_SMS_SDIO_DRV=m - -# -# 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 SDMC DM1105 Adapters -# -CONFIG_DVB_DM1105=m - -# -# Supported FireWire (IEEE 1394) Adapters -# -CONFIG_DVB_FIREDTV=m -CONFIG_DVB_FIREDTV_INPUT=y - -# -# Supported Earthsoft PT1 Adapters -# -# CONFIG_DVB_PT1 is not set - -# -# Supported Mantis Adapters -# -CONFIG_MANTIS_CORE=m -CONFIG_DVB_MANTIS=m -CONFIG_DVB_HOPPER=m - -# -# Supported nGene Adapters -# -CONFIG_DVB_NGENE=m - -# -# Supported ddbridge ('Octopus') Adapters -# -CONFIG_DVB_DDBRIDGE=m - -# -# Supported DVB Frontends -# -# CONFIG_DVB_FE_CUSTOMISE is not set - -# -# Multistandard (satellite) frontends -# -CONFIG_DVB_STB0899=m -CONFIG_DVB_STB6100=m -CONFIG_DVB_STV090x=m -CONFIG_DVB_STV6110x=m - -# -# Multistandard (cable + terrestrial) frontends -# -CONFIG_DVB_DRXK=m -CONFIG_DVB_TDA18271C2DD=m - -# -# DVB-S (satellite) frontends -# -CONFIG_DVB_CX24110=m -CONFIG_DVB_CX24123=m -CONFIG_DVB_MT312=m -CONFIG_DVB_ZL10036=m -CONFIG_DVB_ZL10039=m -CONFIG_DVB_S5H1420=m -CONFIG_DVB_STV0288=m -CONFIG_DVB_STB6000=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_STV6110=m -CONFIG_DVB_STV0900=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA10086=m -CONFIG_DVB_TDA8261=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TUNER_ITD1000=m -CONFIG_DVB_TUNER_CX24113=m -CONFIG_DVB_TDA826X=m -CONFIG_DVB_TUA6100=m -CONFIG_DVB_CX24116=m -CONFIG_DVB_SI21XX=m -CONFIG_DVB_DS3000=m -CONFIG_DVB_MB86A16=m -CONFIG_DVB_TDA10071=m - -# -# DVB-T (terrestrial) frontends -# -CONFIG_DVB_SP8870=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_DRXD=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 -CONFIG_DVB_DIB7000M=m -CONFIG_DVB_DIB7000P=m -CONFIG_DVB_TDA10048=m -CONFIG_DVB_AF9013=m -CONFIG_DVB_EC100=m -CONFIG_DVB_STV0367=m -CONFIG_DVB_CXD2820R=m - -# -# DVB-C (cable) frontends -# -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_TDA10023=m -CONFIG_DVB_STV0297=m - -# -# ATSC (North American/Korean Terrestrial/Cable DTV) frontends -# -CONFIG_DVB_NXT200X=m -CONFIG_DVB_OR51211=m -CONFIG_DVB_OR51132=m -CONFIG_DVB_BCM3510=m -CONFIG_DVB_LGDT330X=m -CONFIG_DVB_LGDT3305=m -CONFIG_DVB_S5H1409=m -CONFIG_DVB_AU8522=m -CONFIG_DVB_S5H1411=m - -# -# ISDB-T (terrestrial) frontends -# -CONFIG_DVB_S921=m -CONFIG_DVB_DIB8000=m -CONFIG_DVB_MB86A20S=m - -# -# Digital terrestrial only tuners/PLL -# -CONFIG_DVB_PLL=m -CONFIG_DVB_TUNER_DIB0070=m -CONFIG_DVB_TUNER_DIB0090=m - -# -# SEC control devices for DVB-S -# -CONFIG_DVB_LNBP21=m -CONFIG_DVB_LNBP22=m -CONFIG_DVB_ISL6405=m -CONFIG_DVB_ISL6421=m -CONFIG_DVB_ISL6423=m -CONFIG_DVB_A8293=m -CONFIG_DVB_LGS8GXX=m -CONFIG_DVB_ATBM8830=m -CONFIG_DVB_TDA665x=m -CONFIG_DVB_IT913X_FE=m - -# -# Tools to develop new frontends -# -# CONFIG_DVB_DUMMY_FE is not set - -# -# Graphics support -# -CONFIG_AGP=m -CONFIG_AGP_AMD64=m -CONFIG_AGP_INTEL=m -CONFIG_AGP_SIS=m -CONFIG_AGP_VIA=m -# CONFIG_VGA_ARB is not set -CONFIG_VGA_SWITCHEROO=y -CONFIG_DRM=m -CONFIG_DRM_KMS_HELPER=m -CONFIG_DRM_TTM=m -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -# CONFIG_DRM_RADEON_KMS is not set -CONFIG_DRM_I810=m -CONFIG_DRM_I915=m -# CONFIG_DRM_I915_KMS is not set -CONFIG_DRM_MGA=m -CONFIG_DRM_SIS=m -CONFIG_DRM_VIA=m -CONFIG_DRM_SAVAGE=m -CONFIG_DRM_VMWGFX=m -# CONFIG_STUB_POULSBO is not set -CONFIG_VGASTATE=m -CONFIG_VIDEO_OUTPUT_CONTROL=m -CONFIG_FB=m -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FB_DDC=m -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -CONFIG_FB_CFB_FILLRECT=m -CONFIG_FB_CFB_COPYAREA=m -CONFIG_FB_CFB_IMAGEBLIT=m -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -CONFIG_FB_SYS_FILLRECT=m -CONFIG_FB_SYS_COPYAREA=m -CONFIG_FB_SYS_IMAGEBLIT=m -# CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_SYS_FOPS=m -# CONFIG_FB_WMT_GE_ROPS is not set -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_HECUBA=m -CONFIG_FB_SVGALIB=m -# CONFIG_FB_MACMODES is not set -CONFIG_FB_BACKLIGHT=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y - -# -# Frame buffer hardware drivers -# -CONFIG_FB_CIRRUS=m -CONFIG_FB_PM2=m -CONFIG_FB_PM2_FIFO_DISCONNECT=y -CONFIG_FB_CYBER2000=m -CONFIG_FB_CYBER2000_DDC=y -CONFIG_FB_ARC=m -CONFIG_FB_VGA16=m -CONFIG_FB_UVESA=m -CONFIG_FB_N411=m -CONFIG_FB_HGA=m -CONFIG_FB_S1D13XXX=m -CONFIG_FB_NVIDIA=m -CONFIG_FB_NVIDIA_I2C=y -# CONFIG_FB_NVIDIA_DEBUG is not set -CONFIG_FB_NVIDIA_BACKLIGHT=y -CONFIG_FB_RIVA=m -CONFIG_FB_RIVA_I2C=y -# CONFIG_FB_RIVA_DEBUG is not set -CONFIG_FB_RIVA_BACKLIGHT=y -CONFIG_FB_LE80578=m -CONFIG_FB_CARILLO_RANCH=m -CONFIG_FB_INTEL=m -# CONFIG_FB_INTEL_DEBUG is not set -CONFIG_FB_INTEL_I2C=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -CONFIG_FB_RADEON=m -CONFIG_FB_RADEON_I2C=y -CONFIG_FB_RADEON_BACKLIGHT=y -# CONFIG_FB_RADEON_DEBUG is not set -CONFIG_FB_ATY128=m -CONFIG_FB_ATY128_BACKLIGHT=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_GENERIC_LCD=y -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_BACKLIGHT=y -CONFIG_FB_S3=m -CONFIG_FB_S3_DDC=y -CONFIG_FB_SAVAGE=m -CONFIG_FB_SAVAGE_I2C=y -CONFIG_FB_SAVAGE_ACCEL=y -CONFIG_FB_SIS=m -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_VIA=m -# CONFIG_FB_VIA_DIRECT_PROCFS is not set -CONFIG_FB_VIA_X_COMPATIBILITY=y -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_KYRO=m -CONFIG_FB_3DFX=m -CONFIG_FB_3DFX_ACCEL=y -CONFIG_FB_3DFX_I2C=y -CONFIG_FB_VOODOO1=m -CONFIG_FB_VT8623=m -CONFIG_FB_TRIDENT=m -CONFIG_FB_ARK=m -CONFIG_FB_PM3=m -CONFIG_FB_CARMINE=m -CONFIG_FB_CARMINE_DRAM_EVAL=y -# CONFIG_CARMINE_DRAM_CUSTOM is not set -CONFIG_FB_GEODE=y -CONFIG_FB_GEODE_LX=m -CONFIG_FB_GEODE_GX=m -CONFIG_FB_GEODE_GX1=m -CONFIG_FB_TMIO=m -CONFIG_FB_TMIO_ACCELL=y -CONFIG_FB_SM501=m -# CONFIG_FB_SMSCUFX is not set -# CONFIG_FB_UDL is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_XEN_FBDEV_FRONTEND=m -CONFIG_FB_METRONOME=m -CONFIG_FB_MB862XX=m -CONFIG_FB_MB862XX_PCI_GDC=y -CONFIG_FB_MB862XX_I2C=y -CONFIG_FB_BROADSHEET=m -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_LCD_L4F00242T03=m -CONFIG_LCD_LMS283GF05=m -CONFIG_LCD_LTV350QV=m -CONFIG_LCD_ILI9320=m -CONFIG_LCD_TDO24M=m -CONFIG_LCD_VGG2432A4=m -CONFIG_LCD_PLATFORM=m -CONFIG_LCD_S6E63M0=m -# CONFIG_LCD_LD9040 is not set -CONFIG_LCD_AMS369FG06=m -CONFIG_BACKLIGHT_CLASS_DEVICE=m -CONFIG_BACKLIGHT_GENERIC=m -CONFIG_BACKLIGHT_PROGEAR=m -CONFIG_BACKLIGHT_CARILLO_RANCH=m -# CONFIG_BACKLIGHT_APPLE is not set -CONFIG_BACKLIGHT_SAHARA=m -CONFIG_BACKLIGHT_ADP8860=m -# CONFIG_BACKLIGHT_ADP8870 is not set -CONFIG_BACKLIGHT_PCF50633=m - -# -# Display device support -# -CONFIG_DISPLAY_SUPPORT=m - -# -# Display hardware drivers -# - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -# CONFIG_VGACON_SOFT_SCROLLBACK is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=m -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_LOGO is not set -CONFIG_SOUND=m -CONFIG_SOUND_OSS_CORE=y -CONFIG_SOUND_OSS_CORE_PRECLAIM=y -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m -CONFIG_SND_RAWMIDI=m -CONFIG_SND_JACK=y -CONFIG_SND_SEQUENCER=m -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_HRTIMER=m -CONFIG_SND_SEQ_HRTIMER_DEFAULT=y -CONFIG_SND_DYNAMIC_MINORS=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -CONFIG_SND_VMASTER=y -CONFIG_SND_DMA_SGBUF=y -CONFIG_SND_RAWMIDI_SEQ=m -CONFIG_SND_OPL3_LIB_SEQ=m -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -CONFIG_SND_EMU10K1_SEQ=m -CONFIG_SND_MPU401_UART=m -CONFIG_SND_OPL3_LIB=m -CONFIG_SND_VX_LIB=m -CONFIG_SND_AC97_CODEC=m -CONFIG_SND_DRIVERS=y -CONFIG_SND_PCSP=m -CONFIG_SND_DUMMY=m -# CONFIG_SND_ALOOP is not set -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -CONFIG_SND_MTS64=m -CONFIG_SND_SERIAL_U16550=m -CONFIG_SND_MPU401=m -CONFIG_SND_PORTMAN2X4=m -CONFIG_SND_AC97_POWER_SAVE=y -CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 -CONFIG_SND_SB_COMMON=m -CONFIG_SND_SB16_DSP=m -CONFIG_SND_TEA575X=m -CONFIG_SND_PCI=y -CONFIG_SND_AD1889=m -CONFIG_SND_ALS300=m -CONFIG_SND_ALS4000=m -CONFIG_SND_ALI5451=m -CONFIG_SND_ASIHPI=m -CONFIG_SND_ATIIXP=m -CONFIG_SND_ATIIXP_MODEM=m -CONFIG_SND_AU8810=m -CONFIG_SND_AU8820=m -CONFIG_SND_AU8830=m -CONFIG_SND_AW2=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_OXYGEN_LIB=m -CONFIG_SND_OXYGEN=m -CONFIG_SND_CS4281=m -CONFIG_SND_CS46XX=m -CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CS5530=m -CONFIG_SND_CS5535AUDIO=m -CONFIG_SND_CTXFI=m -CONFIG_SND_DARLA20=m -CONFIG_SND_GINA20=m -CONFIG_SND_LAYLA20=m -CONFIG_SND_DARLA24=m -CONFIG_SND_GINA24=m -CONFIG_SND_LAYLA24=m -CONFIG_SND_MONA=m -CONFIG_SND_MIA=m -CONFIG_SND_ECHO3G=m -CONFIG_SND_INDIGO=m -CONFIG_SND_INDIGOIO=m -CONFIG_SND_INDIGODJ=m -CONFIG_SND_INDIGOIOX=m -CONFIG_SND_INDIGODJX=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_EMU10K1X=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_ES1968_INPUT=y -CONFIG_SND_ES1968_RADIO=y -CONFIG_SND_FM801=m -# CONFIG_SND_FM801_TEA575X_BOOL is not set -CONFIG_SND_HDA_INTEL=m -CONFIG_SND_HDA_PREALLOC_SIZE=4096 -CONFIG_SND_HDA_HWDEP=y -# CONFIG_SND_HDA_RECONFIG is not set -CONFIG_SND_HDA_INPUT_BEEP=y -CONFIG_SND_HDA_INPUT_BEEP_MODE=0 -CONFIG_SND_HDA_INPUT_JACK=y -# CONFIG_SND_HDA_PATCH_LOADER is not set -CONFIG_SND_HDA_CODEC_REALTEK=y -CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y -CONFIG_SND_HDA_CODEC_ANALOG=y -CONFIG_SND_HDA_CODEC_SIGMATEL=y -CONFIG_SND_HDA_CODEC_VIA=y -CONFIG_SND_HDA_CODEC_HDMI=y -CONFIG_SND_HDA_CODEC_CIRRUS=y -CONFIG_SND_HDA_CODEC_CONEXANT=y -CONFIG_SND_HDA_CODEC_CA0110=y -CONFIG_SND_HDA_CODEC_CA0132=y -CONFIG_SND_HDA_CODEC_CMEDIA=y -CONFIG_SND_HDA_CODEC_SI3054=y -CONFIG_SND_HDA_GENERIC=y -# CONFIG_SND_HDA_POWER_SAVE is not set -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_LOLA=m -CONFIG_SND_LX6464ES=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_MAESTRO3_INPUT=y -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_VIRTUOSO=m -CONFIG_SND_VX222=m -CONFIG_SND_YMFPCI=m -CONFIG_SND_SPI=y -CONFIG_SND_USB=y -CONFIG_SND_USB_AUDIO=m -CONFIG_SND_USB_UA101=m -CONFIG_SND_USB_USX2Y=m -CONFIG_SND_USB_CAIAQ=m -# CONFIG_SND_USB_CAIAQ_INPUT is not set -CONFIG_SND_USB_US122L=m -CONFIG_SND_USB_6FIRE=m -CONFIG_SND_FIREWIRE=y -CONFIG_SND_FIREWIRE_LIB=m -CONFIG_SND_FIREWIRE_SPEAKERS=m -CONFIG_SND_ISIGHT=m -CONFIG_SND_PCMCIA=y -CONFIG_SND_VXPOCKET=m -CONFIG_SND_PDAUDIOCF=m -CONFIG_SND_SOC=m -# CONFIG_SND_SOC_CACHE_LZO is not set -CONFIG_SND_SOC_I2C_AND_SPI=m -CONFIG_SND_SOC_ALL_CODECS=m -CONFIG_SND_SOC_WM_HUBS=m -CONFIG_SND_SOC_AD1836=m -CONFIG_SND_SOC_AD193X=m -CONFIG_SND_SOC_AD73311=m -CONFIG_SND_SOC_ADAU1373=m -CONFIG_SND_SOC_ADAV80X=m -CONFIG_SND_SOC_ADS117X=m -CONFIG_SND_SOC_AK4104=m -CONFIG_SND_SOC_AK4535=m -CONFIG_SND_SOC_AK4641=m -CONFIG_SND_SOC_AK4642=m -CONFIG_SND_SOC_AK4671=m -CONFIG_SND_SOC_ALC5623=m -CONFIG_SND_SOC_CS42L51=m -CONFIG_SND_SOC_CS4270=m -CONFIG_SND_SOC_CS4271=m -CONFIG_SND_SOC_CX20442=m -CONFIG_SND_SOC_JZ4740_CODEC=m -CONFIG_SND_SOC_L3=m -CONFIG_SND_SOC_DA7210=m -CONFIG_SND_SOC_DFBMCS320=m -CONFIG_SND_SOC_MAX98088=m -CONFIG_SND_SOC_MAX98095=m -CONFIG_SND_SOC_MAX9850=m -CONFIG_SND_SOC_PCM3008=m -CONFIG_SND_SOC_RT5631=m -CONFIG_SND_SOC_SGTL5000=m -CONFIG_SND_SOC_SPDIF=m -CONFIG_SND_SOC_SSM2602=m -CONFIG_SND_SOC_STA32X=m -CONFIG_SND_SOC_TLV320AIC23=m -CONFIG_SND_SOC_TLV320AIC26=m -CONFIG_SND_SOC_TLV320AIC32X4=m -CONFIG_SND_SOC_TLV320AIC3X=m -CONFIG_SND_SOC_TLV320DAC33=m -CONFIG_SND_SOC_UDA134X=m -CONFIG_SND_SOC_UDA1380=m -CONFIG_SND_SOC_WL1273=m -CONFIG_SND_SOC_WM1250_EV1=m -CONFIG_SND_SOC_WM5100=m -CONFIG_SND_SOC_WM8400=m -CONFIG_SND_SOC_WM8510=m -CONFIG_SND_SOC_WM8523=m -CONFIG_SND_SOC_WM8580=m -CONFIG_SND_SOC_WM8711=m -CONFIG_SND_SOC_WM8727=m -CONFIG_SND_SOC_WM8728=m -CONFIG_SND_SOC_WM8731=m -CONFIG_SND_SOC_WM8737=m -CONFIG_SND_SOC_WM8741=m -CONFIG_SND_SOC_WM8750=m -CONFIG_SND_SOC_WM8753=m -CONFIG_SND_SOC_WM8770=m -CONFIG_SND_SOC_WM8776=m -CONFIG_SND_SOC_WM8782=m -CONFIG_SND_SOC_WM8804=m -CONFIG_SND_SOC_WM8900=m -CONFIG_SND_SOC_WM8903=m -CONFIG_SND_SOC_WM8904=m -CONFIG_SND_SOC_WM8940=m -CONFIG_SND_SOC_WM8955=m -CONFIG_SND_SOC_WM8960=m -CONFIG_SND_SOC_WM8961=m -CONFIG_SND_SOC_WM8962=m -CONFIG_SND_SOC_WM8971=m -CONFIG_SND_SOC_WM8974=m -CONFIG_SND_SOC_WM8978=m -CONFIG_SND_SOC_WM8983=m -CONFIG_SND_SOC_WM8985=m -CONFIG_SND_SOC_WM8988=m -CONFIG_SND_SOC_WM8990=m -CONFIG_SND_SOC_WM8991=m -CONFIG_SND_SOC_WM8993=m -CONFIG_SND_SOC_WM8995=m -CONFIG_SND_SOC_WM8996=m -CONFIG_SND_SOC_WM9081=m -CONFIG_SND_SOC_LM4857=m -CONFIG_SND_SOC_MAX9877=m -CONFIG_SND_SOC_TPA6130A2=m -CONFIG_SND_SOC_WM2000=m -CONFIG_SND_SOC_WM9090=m -# CONFIG_SOUND_PRIME is not set -CONFIG_AC97_BUS=m -CONFIG_HID_SUPPORT=y -CONFIG_HID=m -CONFIG_HIDRAW=y - -# -# USB Input Devices -# -CONFIG_USB_HID=m -# CONFIG_HID_PID is not set -# CONFIG_USB_HIDDEV is not set - -# -# USB HID Boot Protocol drivers -# -CONFIG_USB_KBD=m -CONFIG_USB_MOUSE=m - -# -# Special HID drivers -# -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -CONFIG_HID_PRODIKEYS=m -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_ELECOM is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_HOLTEK is not set -CONFIG_HID_KEYTOUCH=m -# CONFIG_HID_KYE is not set -# CONFIG_HID_UCLOGIC is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -CONFIG_HID_LCPOWER=m -# CONFIG_HID_LOGITECH is not set -CONFIG_HID_MAGICMOUSE=m -# CONFIG_HID_MICROSOFT is not set -# CONFIG_HID_MONTEREY is not set -CONFIG_HID_MULTITOUCH=m -# CONFIG_HID_NTRIG is not set -CONFIG_HID_ORTEK=m -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -CONFIG_HID_PICOLCD=m -CONFIG_HID_PICOLCD_FB=y -CONFIG_HID_PICOLCD_BACKLIGHT=y -CONFIG_HID_PICOLCD_LCD=y -CONFIG_HID_PICOLCD_LEDS=y -CONFIG_HID_PRIMAX=m -CONFIG_HID_QUANTA=m -CONFIG_HID_ROCCAT=m -CONFIG_HID_ROCCAT_COMMON=m -CONFIG_HID_ROCCAT_ARVO=m -CONFIG_HID_ROCCAT_KONE=m -CONFIG_HID_ROCCAT_KONEPLUS=m -CONFIG_HID_ROCCAT_KOVAPLUS=m -# CONFIG_HID_ROCCAT_PYRA is not set -# CONFIG_HID_SAMSUNG is not set -CONFIG_HID_SONY=m -CONFIG_HID_SPEEDLINK=m -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_WACOM is not set -# CONFIG_HID_WIIMOTE is not set -# CONFIG_HID_ZEROPLUS is not set -CONFIG_HID_ZYDACRON=m -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=m -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -CONFIG_USB_ARCH_HAS_XHCI=y -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -CONFIG_USB_DEVICE_CLASS=y -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set -CONFIG_USB_MON=m -CONFIG_USB_WUSB=m -CONFIG_USB_WUSB_CBAF=m -# CONFIG_USB_WUSB_CBAF_DEBUG is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_C67X00_HCD=m -CONFIG_USB_XHCI_HCD=m -# CONFIG_USB_XHCI_HCD_DEBUGGING is not set -CONFIG_USB_EHCI_HCD=m -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_OXU210HP_HCD=m -CONFIG_USB_ISP116X_HCD=m -CONFIG_USB_ISP1760_HCD=m -CONFIG_USB_ISP1362_HCD=m -CONFIG_USB_OHCI_HCD=m -CONFIG_USB_OHCI_HCD_SSB=y -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -CONFIG_USB_UHCI_HCD=m -CONFIG_USB_U132_HCD=m -CONFIG_USB_SL811_HCD=m -CONFIG_USB_SL811_HCD_ISO=y -CONFIG_USB_SL811_CS=m -CONFIG_USB_R8A66597_HCD=m -CONFIG_USB_WHCI_HCD=m -CONFIG_USB_HWA_HCD=m - -# -# USB Device Class drivers -# -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_WDM=m -CONFIG_USB_TMC=m - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_REALTEK=m -CONFIG_USB_STORAGE_DATAFAB=m -CONFIG_USB_STORAGE_FREECOM=m -CONFIG_USB_STORAGE_ISD200=m -CONFIG_USB_STORAGE_USBAT=m -CONFIG_USB_STORAGE_SDDR09=m -CONFIG_USB_STORAGE_SDDR55=m -CONFIG_USB_STORAGE_JUMPSHOT=m -CONFIG_USB_STORAGE_ALAUDA=m -CONFIG_USB_STORAGE_ONETOUCH=m -CONFIG_USB_STORAGE_KARMA=m -CONFIG_USB_STORAGE_CYPRESS_ATACB=m -CONFIG_USB_STORAGE_ENE_UB6250=m -CONFIG_USB_UAS=m -CONFIG_USB_LIBUSUAL=y - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB port drivers -# -CONFIG_USB_USS720=m -CONFIG_USB_SERIAL=m -CONFIG_USB_EZUSB=y -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_AIRCABLE=m -CONFIG_USB_SERIAL_ARK3116=m -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_CH341=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CP210X=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_IUU=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_MOS7720=m -CONFIG_USB_SERIAL_MOS7715_PARPORT=y -CONFIG_USB_SERIAL_MOS7840=m -CONFIG_USB_SERIAL_MOTOROLA=m -CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_OTI6858=m -CONFIG_USB_SERIAL_QCAUX=m -CONFIG_USB_SERIAL_QUALCOMM=m -CONFIG_USB_SERIAL_SPCP8X5=m -CONFIG_USB_SERIAL_HP4X=m -CONFIG_USB_SERIAL_SAFE=m -CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SERIAL_SIEMENS_MPI=m -CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_USB_SERIAL_SYMBOL=m -CONFIG_USB_SERIAL_TI=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_WWAN=m -CONFIG_USB_SERIAL_OPTION=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_OPTICON=m -CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m -CONFIG_USB_SERIAL_ZIO=m -# CONFIG_USB_SERIAL_SSU100 is not set -CONFIG_USB_SERIAL_DEBUG=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_EMI62=m -CONFIG_USB_EMI26=m -CONFIG_USB_ADUTUX=m -CONFIG_USB_SEVSEG=m -CONFIG_USB_RIO500=m -# CONFIG_USB_LEGOTOWER is not set -CONFIG_USB_LCD=m -CONFIG_USB_LED=m -CONFIG_USB_CYPRESS_CY7C63=m -CONFIG_USB_CYTHERM=m -CONFIG_USB_IDMOUSE=m -CONFIG_USB_FTDI_ELAN=m -# CONFIG_USB_APPLEDISPLAY is not set -CONFIG_USB_SISUSBVGA=m -CONFIG_USB_SISUSBVGA_CON=y -CONFIG_USB_LD=m -# CONFIG_USB_TRANCEVIBRATOR is not set -CONFIG_USB_IOWARRIOR=m -CONFIG_USB_TEST=m -CONFIG_USB_ISIGHTFW=m -# CONFIG_USB_YUREX is not set -CONFIG_USB_ATM=m -CONFIG_USB_SPEEDTOUCH=m -CONFIG_USB_CXACRU=m -CONFIG_USB_UEAGLEATM=m -CONFIG_USB_XUSBATM=m -# CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -CONFIG_USB_GPIO_VBUS=m -CONFIG_NOP_USB_XCEIV=m -CONFIG_UWB=m -CONFIG_UWB_HWA=m -CONFIG_UWB_WHCI=m -CONFIG_UWB_I1480U=m -CONFIG_MMC=m -# CONFIG_MMC_DEBUG is not set -# CONFIG_MMC_UNSAFE_RESUME is not set -# CONFIG_MMC_CLKGATE is not set - -# -# MMC/SD/SDIO Card Drivers -# -CONFIG_MMC_BLOCK=m -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y -CONFIG_SDIO_UART=m -CONFIG_MMC_TEST=m - -# -# MMC/SD/SDIO Host Controller Drivers -# -CONFIG_MMC_SDHCI=m -CONFIG_MMC_SDHCI_PCI=m -CONFIG_MMC_RICOH_MMC=y -CONFIG_MMC_SDHCI_PLTFM=m -CONFIG_MMC_WBSD=m -CONFIG_MMC_TIFM_SD=m -# CONFIG_MMC_SPI is not set -CONFIG_MMC_SDRICOH_CS=m -CONFIG_MMC_CB710=m -CONFIG_MMC_VIA_SDMMC=m -CONFIG_MMC_VUB300=m -# CONFIG_MMC_USHC is not set -CONFIG_MEMSTICK=m -# CONFIG_MEMSTICK_DEBUG is not set - -# -# MemoryStick drivers -# -# CONFIG_MEMSTICK_UNSAFE_RESUME is not set -CONFIG_MSPRO_BLOCK=m - -# -# MemoryStick Host Controller Drivers -# -CONFIG_MEMSTICK_TIFM_MS=m -CONFIG_MEMSTICK_JMICRON_38X=m -CONFIG_MEMSTICK_R592=m -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y - -# -# LED drivers -# -CONFIG_LEDS_LM3530=m -CONFIG_LEDS_NET5501=m -CONFIG_LEDS_PCA9532=m -# CONFIG_LEDS_PCA9532_GPIO is not set -CONFIG_LEDS_GPIO=m -CONFIG_LEDS_LP3944=m -# CONFIG_LEDS_LP5521 is not set -# CONFIG_LEDS_LP5523 is not set -CONFIG_LEDS_CLEVO_MAIL=m -CONFIG_LEDS_PCA955X=m -CONFIG_LEDS_DAC124S085=m -CONFIG_LEDS_BD2802=m -CONFIG_LEDS_INTEL_SS4200=m -CONFIG_LEDS_LT3593=m -CONFIG_LEDS_DELL_NETBOOKS=m -# CONFIG_LEDS_MC13783 is not set -CONFIG_LEDS_TRIGGERS=y - -# -# LED Triggers -# -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_LEDS_TRIGGER_BACKLIGHT=m -CONFIG_LEDS_TRIGGER_GPIO=m -CONFIG_LEDS_TRIGGER_DEFAULT_ON=m - -# -# iptables trigger is under Netfilter config (LED target) -# -CONFIG_ACCESSIBILITY=y -# CONFIG_A11Y_BRAILLE_CONSOLE is not set -CONFIG_INFINIBAND=m -CONFIG_INFINIBAND_USER_MAD=m -CONFIG_INFINIBAND_USER_ACCESS=m -CONFIG_INFINIBAND_USER_MEM=y -CONFIG_INFINIBAND_ADDR_TRANS=y -CONFIG_INFINIBAND_MTHCA=m -# CONFIG_INFINIBAND_MTHCA_DEBUG is not set -# CONFIG_INFINIBAND_IPATH is not set -# CONFIG_INFINIBAND_QIB is not set -CONFIG_INFINIBAND_AMSO1100=m -# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set -CONFIG_INFINIBAND_CXGB3=m -# CONFIG_INFINIBAND_CXGB3_DEBUG is not set -CONFIG_INFINIBAND_CXGB4=m -CONFIG_MLX4_INFINIBAND=m -CONFIG_INFINIBAND_NES=m -# CONFIG_INFINIBAND_NES_DEBUG is not set -CONFIG_INFINIBAND_IPOIB=m -# CONFIG_INFINIBAND_IPOIB_CM is not set -# CONFIG_INFINIBAND_IPOIB_DEBUG is not set -CONFIG_INFINIBAND_SRP=m -CONFIG_INFINIBAND_ISER=m -# CONFIG_EDAC is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -CONFIG_RTC_INTF_DEV_UIE_EMUL=y -CONFIG_RTC_DRV_TEST=m - -# -# I2C RTC drivers -# -CONFIG_RTC_DRV_DS1307=m -CONFIG_RTC_DRV_DS1374=m -CONFIG_RTC_DRV_DS1672=m -# CONFIG_RTC_DRV_DS3232 is not set -CONFIG_RTC_DRV_MAX6900=m -CONFIG_RTC_DRV_RS5C372=m -CONFIG_RTC_DRV_ISL1208=m -# CONFIG_RTC_DRV_ISL12022 is not set -CONFIG_RTC_DRV_X1205=m -CONFIG_RTC_DRV_PCF8563=m -CONFIG_RTC_DRV_PCF8583=m -CONFIG_RTC_DRV_M41T80=m -CONFIG_RTC_DRV_M41T80_WDT=y -CONFIG_RTC_DRV_BQ32K=m -CONFIG_RTC_DRV_S35390A=m -CONFIG_RTC_DRV_FM3130=m -CONFIG_RTC_DRV_RX8581=m -CONFIG_RTC_DRV_RX8025=m -CONFIG_RTC_DRV_EM3027=m -CONFIG_RTC_DRV_RV3029C2=m - -# -# SPI RTC drivers -# -CONFIG_RTC_DRV_M41T93=m -CONFIG_RTC_DRV_M41T94=m -CONFIG_RTC_DRV_DS1305=m -CONFIG_RTC_DRV_DS1390=m -CONFIG_RTC_DRV_MAX6902=m -CONFIG_RTC_DRV_R9701=m -CONFIG_RTC_DRV_RS5C348=m -CONFIG_RTC_DRV_DS3234=m -CONFIG_RTC_DRV_PCF2123=m - -# -# Platform RTC drivers -# -CONFIG_RTC_DRV_CMOS=y -CONFIG_RTC_DRV_DS1286=m -CONFIG_RTC_DRV_DS1511=m -CONFIG_RTC_DRV_DS1553=m -CONFIG_RTC_DRV_DS1742=m -CONFIG_RTC_DRV_STK17TA8=m -CONFIG_RTC_DRV_M48T86=m -CONFIG_RTC_DRV_M48T35=m -CONFIG_RTC_DRV_M48T59=m -CONFIG_RTC_DRV_MSM6242=m -CONFIG_RTC_DRV_BQ4802=m -CONFIG_RTC_DRV_RP5C01=m -CONFIG_RTC_DRV_V3020=m -CONFIG_RTC_DRV_PCF50633=m - -# -# on-CPU RTC drivers -# -# CONFIG_RTC_DRV_MC13XXX is not set -CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# -# CONFIG_INTEL_MID_DMAC is not set -CONFIG_INTEL_IOATDMA=m -CONFIG_TIMB_DMA=m -CONFIG_PCH_DMA=m -CONFIG_DMA_ENGINE=y - -# -# DMA Clients -# -CONFIG_NET_DMA=y -# CONFIG_ASYNC_TX_DMA is not set -CONFIG_DMATEST=m -CONFIG_DCA=m -CONFIG_AUXDISPLAY=y -CONFIG_KS0108=m -CONFIG_KS0108_PORT=0x378 -CONFIG_KS0108_DELAY=2 -CONFIG_CFAG12864B=m -CONFIG_CFAG12864B_RATE=20 -CONFIG_UIO=m -CONFIG_UIO_CIF=m -CONFIG_UIO_PDRV=m -CONFIG_UIO_PDRV_GENIRQ=m -CONFIG_UIO_AEC=m -CONFIG_UIO_SERCOS3=m -CONFIG_UIO_PCI_GENERIC=m -CONFIG_UIO_NETX=m -CONFIG_VIRTIO=m -CONFIG_VIRTIO_RING=m - -# -# Virtio drivers -# -CONFIG_VIRTIO_PCI=m -CONFIG_VIRTIO_BALLOON=m -CONFIG_VIRTIO_MMIO=m - -# -# Xen driver support -# -CONFIG_XEN_BALLOON=y -CONFIG_XEN_SCRUB_PAGES=y -CONFIG_XEN_DEV_EVTCHN=m -CONFIG_XEN_BACKEND=y -CONFIG_XENFS=m -CONFIG_XEN_COMPAT_XENFS=y -CONFIG_XEN_SYS_HYPERVISOR=y -CONFIG_XEN_XENBUS_FRONTEND=y -CONFIG_XEN_GNTDEV=m -CONFIG_XEN_GRANT_DEV_ALLOC=m -CONFIG_SWIOTLB_XEN=y -CONFIG_XEN_PCIDEV_BACKEND=m -CONFIG_STAGING=y -# CONFIG_ET131X is not set -# CONFIG_SLICOSS is not set -CONFIG_USBIP_CORE=m -CONFIG_USBIP_VHCI_HCD=m -CONFIG_USBIP_HOST=m -# CONFIG_USBIP_DEBUG is not set -# CONFIG_W35UND is not set -# CONFIG_PRISM2_USB is not set -# CONFIG_ECHO is not set -# CONFIG_COMEDI is not set -# CONFIG_ASUS_OLED is not set -# CONFIG_PANEL is not set -# CONFIG_R8187SE is not set -# CONFIG_RTL8192U is not set -# CONFIG_RTL8192E is not set -# CONFIG_R8712U is not set -# CONFIG_RTS_PSTOR is not set -# CONFIG_RTS5139 is not set -# CONFIG_TRANZPORT is not set -# CONFIG_POHMELFS is not set -# CONFIG_IDE_PHISON is not set -# CONFIG_LINE6_USB is not set -CONFIG_DRM_NOUVEAU=m -CONFIG_DRM_NOUVEAU_BACKLIGHT=y -CONFIG_DRM_NOUVEAU_DEBUG=y - -# -# I2C encoder or helper chips -# -# CONFIG_DRM_I2C_CH7006 is not set -CONFIG_DRM_I2C_SIL164=m -# CONFIG_USB_SERIAL_QUATECH2 is not set -# CONFIG_USB_SERIAL_QUATECH_USB2 is not set -# CONFIG_VT6655 is not set -# CONFIG_VT6656 is not set -CONFIG_HYPERV_STORAGE=m -CONFIG_HYPERV_NET=m -CONFIG_HYPERV_MOUSE=m -# CONFIG_VME_BUS is not set -# CONFIG_DX_SEP is not set -# CONFIG_IIO is not set -# CONFIG_XVMALLOC is not set -# CONFIG_ZRAM is not set -# CONFIG_WLAGS49_H2 is not set -# CONFIG_WLAGS49_H25 is not set -# CONFIG_FB_SM7XX is not set -# CONFIG_CRYSTALHD is not set -# CONFIG_CXT1E1 is not set -# CONFIG_FB_XGI is not set -# CONFIG_ACPI_QUICKSTART is not set -# CONFIG_SBE_2T3E3 is not set -# CONFIG_USB_ENESTORAGE is not set -# CONFIG_BCM_WIMAX is not set -# CONFIG_FT1000 is not set - -# -# Speakup console speech -# -# CONFIG_SPEAKUP is not set -# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set -# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set -# CONFIG_DRM_PSB is not set -# CONFIG_INTEL_MEI is not set -# CONFIG_STAGING_MEDIA is not set -CONFIG_X86_PLATFORM_DEVICES=y -CONFIG_ACER_WMI=m -CONFIG_ACERHDF=m -CONFIG_ASUS_LAPTOP=m -CONFIG_DELL_LAPTOP=m -CONFIG_DELL_WMI=m -CONFIG_DELL_WMI_AIO=m -CONFIG_FUJITSU_LAPTOP=m -# CONFIG_FUJITSU_LAPTOP_DEBUG is not set -CONFIG_HP_ACCEL=m -CONFIG_HP_WMI=m -CONFIG_MSI_LAPTOP=m -CONFIG_PANASONIC_LAPTOP=m -CONFIG_COMPAL_LAPTOP=m -CONFIG_SONY_LAPTOP=m -# CONFIG_SONYPI_COMPAT is not set -CONFIG_IDEAPAD_LAPTOP=m -CONFIG_THINKPAD_ACPI=m -CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y -# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set -# CONFIG_THINKPAD_ACPI_DEBUG is not set -# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set -CONFIG_THINKPAD_ACPI_VIDEO=y -CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y -CONFIG_SENSORS_HDAPS=m -CONFIG_INTEL_MENLOW=m -CONFIG_EEEPC_LAPTOP=m -CONFIG_ASUS_WMI=m -CONFIG_ASUS_NB_WMI=m -CONFIG_EEEPC_WMI=m -CONFIG_ACPI_WMI=m -CONFIG_MSI_WMI=m -CONFIG_ACPI_ASUS=m -# CONFIG_TOPSTAR_LAPTOP is not set -CONFIG_ACPI_TOSHIBA=m -CONFIG_TOSHIBA_BT_RFKILL=m -CONFIG_ACPI_CMPC=m -# CONFIG_INTEL_IPS is not set -# CONFIG_IBM_RTL is not set -CONFIG_XO15_EBOOK=m -# CONFIG_SAMSUNG_LAPTOP is not set -CONFIG_MXM_WMI=m -CONFIG_INTEL_OAKTRAIL=m -# CONFIG_SAMSUNG_Q10 is not set - -# -# Hardware Spinlock drivers -# -CONFIG_CLKEVT_I8253=y -CONFIG_I8253_LOCK=y -CONFIG_CLKBLD_I8253=y -CONFIG_IOMMU_API=y -CONFIG_IOMMU_SUPPORT=y -CONFIG_AMD_IOMMU=y -CONFIG_AMD_IOMMU_STATS=y -CONFIG_DMAR_TABLE=y -CONFIG_INTEL_IOMMU=y -# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set -CONFIG_INTEL_IOMMU_FLOPPY_WA=y -CONFIG_IRQ_REMAP=y -CONFIG_VIRT_DRIVERS=y -CONFIG_HYPERV=m -CONFIG_HYPERV_UTILS=m -# CONFIG_PM_DEVFREQ is not set - -# -# Firmware Drivers -# -CONFIG_EDD=m -# CONFIG_EDD_OFF is not set -CONFIG_FIRMWARE_MEMMAP=y -CONFIG_DELL_RBU=m -CONFIG_DCDBAS=m -CONFIG_DMIID=y -# CONFIG_DMI_SYSFS is not set -# CONFIG_ISCSI_IBFT_FIND is not set -# CONFIG_SIGMA is not set -# CONFIG_GOOGLE_FIRMWARE is not set - -# -# File systems -# -CONFIG_EXT2_FS=m -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_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_EXT4_FS=m -CONFIG_EXT4_FS_XATTR=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y -# CONFIG_EXT4_DEBUG is not set -CONFIG_FS_XIP=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_JBD2=m -# CONFIG_JBD2_DEBUG is not set -CONFIG_FS_MBCACHE=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -# CONFIG_REISERFS_FS_SECURITY is not set -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_SECURITY=y -# CONFIG_JFS_DEBUG is not set -CONFIG_JFS_STATISTICS=y -CONFIG_XFS_FS=m -CONFIG_XFS_QUOTA=y -CONFIG_XFS_POSIX_ACL=y -CONFIG_XFS_RT=y -# CONFIG_XFS_DEBUG is not set -CONFIG_GFS2_FS=m -CONFIG_GFS2_FS_LOCKING_DLM=y -CONFIG_OCFS2_FS=m -CONFIG_OCFS2_FS_O2CB=m -CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m -CONFIG_OCFS2_FS_STATS=y -CONFIG_OCFS2_DEBUG_MASKLOG=y -# CONFIG_OCFS2_DEBUG_FS is not set -CONFIG_BTRFS_FS=m -CONFIG_BTRFS_FS_POSIX_ACL=y -CONFIG_NILFS2_FS=m -CONFIG_FS_POSIX_ACL=y -CONFIG_EXPORTFS=m -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -# CONFIG_DNOTIFY is not set -CONFIG_INOTIFY_USER=y -# CONFIG_FANOTIFY is not set -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set -# CONFIG_QUOTA_DEBUG is not set -CONFIG_QUOTA_TREE=m -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_QUOTACTL=y -CONFIG_QUOTACTL_COMPAT=y -CONFIG_AUTOFS4_FS=m -CONFIG_FUSE_FS=m -# CONFIG_CUSE is not set - -# -# Caches -# -CONFIG_FSCACHE=m -CONFIG_FSCACHE_STATS=y -CONFIG_FSCACHE_HISTOGRAM=y -# CONFIG_FSCACHE_DEBUG is not set -# CONFIG_FSCACHE_OBJECT_LIST is not set -CONFIG_CACHEFILES=m -# CONFIG_CACHEFILES_DEBUG is not set -# CONFIG_CACHEFILES_HISTOGRAM is not set - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_UDF_FS=m -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="utf8" -CONFIG_NTFS_FS=m -# CONFIG_NTFS_DEBUG is not set -CONFIG_NTFS_RW=y - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_PROC_KCORE is not set -CONFIG_PROC_SYSCTL=y -# CONFIG_PROC_PAGE_MONITOR is not set -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_TMPFS_XATTR is not set -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_CONFIGFS_FS=m -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -CONFIG_ECRYPT_FS=m -CONFIG_HFS_FS=m -CONFIG_HFSPLUS_FS=m -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EFS_FS=m -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -CONFIG_JFFS2_SUMMARY=y -CONFIG_JFFS2_FS_XATTR=y -CONFIG_JFFS2_FS_POSIX_ACL=y -CONFIG_JFFS2_FS_SECURITY=y -CONFIG_JFFS2_COMPRESSION_OPTIONS=y -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_LZO=y -CONFIG_JFFS2_RTIME=y -CONFIG_JFFS2_RUBIN=y -# CONFIG_JFFS2_CMODE_NONE is not set -CONFIG_JFFS2_CMODE_PRIORITY=y -# CONFIG_JFFS2_CMODE_SIZE is not set -# CONFIG_JFFS2_CMODE_FAVOURLZO is not set -CONFIG_UBIFS_FS=m -# CONFIG_UBIFS_FS_XATTR is not set -# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -CONFIG_UBIFS_FS_LZO=y -CONFIG_UBIFS_FS_ZLIB=y -# CONFIG_UBIFS_FS_DEBUG is not set -CONFIG_LOGFS=m -CONFIG_CRAMFS=m -CONFIG_SQUASHFS=m -CONFIG_SQUASHFS_XATTR=y -CONFIG_SQUASHFS_ZLIB=y -# CONFIG_SQUASHFS_LZO is not set -CONFIG_SQUASHFS_XZ=y -# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set -# CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -# CONFIG_VXFS_FS is not set -CONFIG_MINIX_FS=m -CONFIG_OMFS_FS=m -CONFIG_HPFS_FS=m -# CONFIG_QNX4FS_FS is not set -CONFIG_ROMFS_FS=m -CONFIG_ROMFS_BACKED_BY_BLOCK=y -# CONFIG_ROMFS_BACKED_BY_MTD is not set -# CONFIG_ROMFS_BACKED_BY_BOTH is not set -CONFIG_ROMFS_ON_BLOCK=y -CONFIG_PSTORE=y -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_UFS_DEBUG is not set -CONFIG_EXOFS_FS=m -# CONFIG_EXOFS_DEBUG is not set -CONFIG_ORE=m -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -CONFIG_NFS_V4=y -# CONFIG_NFS_V4_1 is not set -# CONFIG_NFS_FSCACHE is not set -# CONFIG_NFS_USE_LEGACY_DNS is not set -CONFIG_NFS_USE_KERNEL_DNS=y -# CONFIG_NFS_USE_NEW_IDMAPPER is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V3_ACL is not set -CONFIG_NFSD_V4=y -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_SUNRPC_XPRT_RDMA=m -CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_CEPH_FS=m -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_WEAK_PW_HASH is not set -# CONFIG_CIFS_UPCALL is not set -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -# CONFIG_CIFS_DEBUG2 is not set -CONFIG_CIFS_DFS_UPCALL=y -# CONFIG_CIFS_FSCACHE is not set -CONFIG_CIFS_ACL=y -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m -CONFIG_DLM=m -# CONFIG_DLM_DEBUG is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_PRINTK_TIME=y -CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -CONFIG_ENABLE_WARN_DEPRECATED=y -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -CONFIG_MAGIC_SYSRQ=y -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_SECTION_MISMATCH is not set -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_SHIRQ=y -CONFIG_LOCKUP_DETECTOR=y -CONFIG_HARDLOCKUP_DETECTOR=y -# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -# CONFIG_DETECT_HUNG_TASK is not set -CONFIG_SCHED_DEBUG=y -CONFIG_SCHEDSTATS=y -CONFIG_TIMER_STATS=y -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_SLUB_STATS is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_SPARSE_RCU_POINTER is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set -CONFIG_ARCH_WANT_FRAME_POINTERS=y -CONFIG_FRAME_POINTER=y -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_KPROBES_SANITY_TEST is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_LKDTM is not set -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -# CONFIG_FAULT_INJECTION is not set -CONFIG_LATENCYTOP=y -CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y -CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_RING_BUFFER=y -CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING_SUPPORT=y -# CONFIG_FTRACE is not set -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set -# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_ASYNC_RAID6_TEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -CONFIG_HAVE_ARCH_KMEMCHECK=y -CONFIG_TEST_KSTRTOX=m -CONFIG_STRICT_DEVMEM=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_EARLY_PRINTK is not set -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_X86_PTDUMP is not set -CONFIG_DEBUG_RODATA=y -# CONFIG_DEBUG_RODATA_TEST is not set -CONFIG_DEBUG_SET_MODULE_RONX=y -CONFIG_DEBUG_NX_TEST=m -# CONFIG_IOMMU_DEBUG is not set -# CONFIG_IOMMU_STRESS is not set -CONFIG_HAVE_MMIOTRACE_SUPPORT=y -CONFIG_X86_DECODER_SELFTEST=y -CONFIG_IO_DELAY_TYPE_0X80=0 -CONFIG_IO_DELAY_TYPE_0XED=1 -CONFIG_IO_DELAY_TYPE_UDELAY=2 -CONFIG_IO_DELAY_TYPE_NONE=3 -CONFIG_IO_DELAY_0X80=y -# CONFIG_IO_DELAY_0XED is not set -# CONFIG_IO_DELAY_UDELAY is not set -# CONFIG_IO_DELAY_NONE is not set -CONFIG_DEFAULT_IO_DELAY_TYPE=0 -CONFIG_DEBUG_BOOT_PARAMS=y -# CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set - -# -# Security options -# -CONFIG_KEYS=y -CONFIG_TRUSTED_KEYS=m -CONFIG_ENCRYPTED_KEYS=m -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -CONFIG_SECURITY=y -CONFIG_SECURITYFS=y -# CONFIG_SECURITY_NETWORK is not set -# CONFIG_SECURITY_PATH is not set -# CONFIG_INTEL_TXT is not set -# CONFIG_SECURITY_TOMOYO is not set -# CONFIG_SECURITY_APPARMOR is not set -# CONFIG_IMA is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_XOR_BLOCKS=m -CONFIG_ASYNC_CORE=m -CONFIG_ASYNC_MEMCPY=m -CONFIG_ASYNC_XOR=m -CONFIG_ASYNC_PQ=m -CONFIG_ASYNC_RAID6_RECOV=m -CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y -CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD=m -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=m -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG=m -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_PCOMP=m -CONFIG_CRYPTO_PCOMP2=y -CONFIG_CRYPTO_MANAGER=m -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_USER=m -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -CONFIG_CRYPTO_GF128MUL=m -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_PCRYPT=m -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_AUTHENC=m -CONFIG_CRYPTO_TEST=m - -# -# Authenticated Encryption with Associated Data -# -CONFIG_CRYPTO_CCM=m -CONFIG_CRYPTO_GCM=m -CONFIG_CRYPTO_SEQIV=m - -# -# Block modes -# -CONFIG_CRYPTO_CBC=m -CONFIG_CRYPTO_CTR=m -CONFIG_CRYPTO_CTS=m -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_LRW=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_XTS=m - -# -# Hash modes -# -CONFIG_CRYPTO_HMAC=m -CONFIG_CRYPTO_XCBC=m -CONFIG_CRYPTO_VMAC=m - -# -# Digest -# -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_CRC32C_INTEL=m -CONFIG_CRYPTO_GHASH=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_RMD128=m -CONFIG_CRYPTO_RMD160=m -CONFIG_CRYPTO_RMD256=m -CONFIG_CRYPTO_RMD320=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA1_SSSE3=m -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m - -# -# Ciphers -# -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_AES_X86_64=m -CONFIG_CRYPTO_AES_NI_INTEL=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_BLOWFISH_COMMON=m -CONFIG_CRYPTO_BLOWFISH_X86_64=m -CONFIG_CRYPTO_CAMELLIA=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SALSA20=m -CONFIG_CRYPTO_SALSA20_X86_64=m -CONFIG_CRYPTO_SEED=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m -CONFIG_CRYPTO_TWOFISH_X86_64=m -CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m - -# -# Compression -# -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_ZLIB=m -CONFIG_CRYPTO_LZO=m - -# -# Random Number Generation -# -CONFIG_CRYPTO_ANSI_CPRNG=m -CONFIG_CRYPTO_USER_API=m -CONFIG_CRYPTO_USER_API_HASH=m -CONFIG_CRYPTO_USER_API_SKCIPHER=m -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_DEV_PADLOCK=m -CONFIG_CRYPTO_DEV_PADLOCK_AES=m -CONFIG_CRYPTO_DEV_PADLOCK_SHA=m -CONFIG_HAVE_KVM=y -CONFIG_HAVE_KVM_IRQCHIP=y -CONFIG_HAVE_KVM_EVENTFD=y -CONFIG_KVM_APIC_ARCHITECTURE=y -CONFIG_KVM_MMIO=y -CONFIG_KVM_ASYNC_PF=y -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=m -CONFIG_KVM_INTEL=m -CONFIG_KVM_AMD=m -CONFIG_VHOST_NET=m -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_RAID6_PQ=m -CONFIG_BITREVERSE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_CRC_CCITT=m -CONFIG_CRC16=m -CONFIG_CRC_T10DIF=m -CONFIG_CRC_ITU_T=m -CONFIG_CRC32=y -CONFIG_CRC7=m -CONFIG_LIBCRC32C=m -CONFIG_CRC8=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_XZ_DEC=y -CONFIG_XZ_DEC_X86=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_IA64=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_BCJ=y -# CONFIG_XZ_DEC_TEST is not set -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DECOMPRESS_XZ=y -CONFIG_DECOMPRESS_LZO=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_REED_SOLOMON=m -CONFIG_REED_SOLOMON_DEC16=y -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m -CONFIG_BTREE=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_CHECK_SIGNATURE=y -CONFIG_CPU_RMAP=y -CONFIG_NLATTR=y -CONFIG_AVERAGE=y -CONFIG_CORDIC=m diff --git a/main/linux-scst/scst-2.2.0-3.2.2.patch b/main/linux-scst/scst-2.2.0-3.2.2.patch deleted file mode 100644 index 68e90a791..000000000 --- a/main/linux-scst/scst-2.2.0-3.2.2.patch +++ /dev/null @@ -1,80901 +0,0 @@ -=== modified file 'block/blk-map.c' ---- old/block/blk-map.c 2012-01-10 22:58:17 +0000 -+++ new/block/blk-map.c 2012-01-10 23:01:21 +0000 -@@ -5,6 +5,8 @@ - #include <linux/module.h> - #include <linux/bio.h> - #include <linux/blkdev.h> -+#include <linux/scatterlist.h> -+#include <linux/slab.h> - #include <scsi/sg.h> /* for struct sg_iovec */ - - #include "blk.h" -@@ -275,6 +277,339 @@ int blk_rq_unmap_user(struct bio *bio) - } - EXPORT_SYMBOL(blk_rq_unmap_user); - -+struct blk_kern_sg_work { -+ atomic_t bios_inflight; -+ struct sg_table sg_table; -+ struct scatterlist *src_sgl; -+}; -+ -+static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw) -+{ -+ struct sg_table *sgt = &bw->sg_table; -+ struct scatterlist *sg; -+ int i; -+ -+ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { -+ struct page *pg = sg_page(sg); -+ if (pg == NULL) -+ break; -+ __free_page(pg); -+ } -+ -+ sg_free_table(sgt); -+ kfree(bw); -+ return; -+} -+ -+static void blk_bio_map_kern_endio(struct bio *bio, int err) -+{ -+ struct blk_kern_sg_work *bw = bio->bi_private; -+ -+ if (bw != NULL) { -+ /* Decrement the bios in processing and, if zero, free */ -+ BUG_ON(atomic_read(&bw->bios_inflight) <= 0); -+ if (atomic_dec_and_test(&bw->bios_inflight)) { -+ if ((bio_data_dir(bio) == READ) && (err == 0)) { -+ unsigned long flags; -+ -+ local_irq_save(flags); /* to protect KMs */ -+ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0, -+ KM_BIO_DST_IRQ, KM_BIO_SRC_IRQ); -+ local_irq_restore(flags); -+ } -+ blk_free_kern_sg_work(bw); -+ } -+ } -+ -+ bio_put(bio); -+ return; -+} -+ -+static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl, -+ int nents, struct blk_kern_sg_work **pbw, -+ gfp_t gfp, gfp_t page_gfp) -+{ -+ int res = 0, i; -+ struct scatterlist *sg; -+ struct scatterlist *new_sgl; -+ int new_sgl_nents; -+ size_t len = 0, to_copy; -+ struct blk_kern_sg_work *bw; -+ -+ bw = kzalloc(sizeof(*bw), gfp); -+ if (bw == NULL) -+ goto out; -+ -+ bw->src_sgl = sgl; -+ -+ for_each_sg(sgl, sg, nents, i) -+ len += sg->length; -+ to_copy = len; -+ -+ new_sgl_nents = PFN_UP(len); -+ -+ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp); -+ if (res != 0) -+ goto err_free; -+ -+ new_sgl = bw->sg_table.sgl; -+ -+ for_each_sg(new_sgl, sg, new_sgl_nents, i) { -+ struct page *pg; -+ -+ pg = alloc_page(page_gfp); -+ if (pg == NULL) -+ goto err_free; -+ -+ sg_assign_page(sg, pg); -+ sg->length = min_t(size_t, PAGE_SIZE, len); -+ -+ len -= PAGE_SIZE; -+ } -+ -+ if (rq_data_dir(rq) == WRITE) { -+ /* -+ * We need to limit amount of copied data to to_copy, because -+ * sgl might have the last element in sgl not marked as last in -+ * SG chaining. -+ */ -+ sg_copy(new_sgl, sgl, 0, to_copy, -+ KM_USER0, KM_USER1); -+ } -+ -+ *pbw = bw; -+ /* -+ * REQ_COPY_USER name is misleading. It should be something like -+ * REQ_HAS_TAIL_SPACE_FOR_PADDING. -+ */ -+ rq->cmd_flags |= REQ_COPY_USER; -+ -+out: -+ return res; -+ -+err_free: -+ blk_free_kern_sg_work(bw); -+ res = -ENOMEM; -+ goto out; -+} -+ -+static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl, -+ int nents, struct blk_kern_sg_work *bw, gfp_t gfp) -+{ -+ int res; -+ struct request_queue *q = rq->q; -+ int rw = rq_data_dir(rq); -+ int max_nr_vecs, i; -+ size_t tot_len; -+ bool need_new_bio; -+ struct scatterlist *sg, *prev_sg = NULL; -+ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL; -+ int bios; -+ -+ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) { -+ WARN_ON(1); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ /* -+ * Let's keep each bio allocation inside a single page to decrease -+ * probability of failure. -+ */ -+ max_nr_vecs = min_t(size_t, -+ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)), -+ BIO_MAX_PAGES); -+ -+ need_new_bio = true; -+ tot_len = 0; -+ bios = 0; -+ for_each_sg(sgl, sg, nents, i) { -+ struct page *page = sg_page(sg); -+ void *page_addr = page_address(page); -+ size_t len = sg->length, l; -+ size_t offset = sg->offset; -+ -+ tot_len += len; -+ prev_sg = sg; -+ -+ /* -+ * Each segment must be aligned on DMA boundary and -+ * not on stack. The last one may have unaligned -+ * length as long as the total length is aligned to -+ * DMA padding alignment. -+ */ -+ if (i == nents - 1) -+ l = 0; -+ else -+ l = len; -+ if (((sg->offset | l) & queue_dma_alignment(q)) || -+ (page_addr && object_is_on_stack(page_addr + sg->offset))) { -+ res = -EINVAL; -+ goto out_free_bios; -+ } -+ -+ while (len > 0) { -+ size_t bytes; -+ int rc; -+ -+ if (need_new_bio) { -+ bio = bio_kmalloc(gfp, max_nr_vecs); -+ if (bio == NULL) { -+ res = -ENOMEM; -+ goto out_free_bios; -+ } -+ -+ if (rw == WRITE) -+ bio->bi_rw |= REQ_WRITE; -+ -+ bios++; -+ bio->bi_private = bw; -+ bio->bi_end_io = blk_bio_map_kern_endio; -+ -+ if (hbio == NULL) -+ hbio = tbio = bio; -+ else -+ tbio = tbio->bi_next = bio; -+ } -+ -+ bytes = min_t(size_t, len, PAGE_SIZE - offset); -+ -+ rc = bio_add_pc_page(q, bio, page, bytes, offset); -+ if (rc < bytes) { -+ if (unlikely(need_new_bio || (rc < 0))) { -+ if (rc < 0) -+ res = rc; -+ else -+ res = -EIO; -+ goto out_free_bios; -+ } else { -+ need_new_bio = true; -+ len -= rc; -+ offset += rc; -+ continue; -+ } -+ } -+ -+ need_new_bio = false; -+ offset = 0; -+ len -= bytes; -+ page = nth_page(page, 1); -+ } -+ } -+ -+ if (hbio == NULL) { -+ res = -EINVAL; -+ goto out_free_bios; -+ } -+ -+ /* Total length must be aligned on DMA padding alignment */ -+ if ((tot_len & q->dma_pad_mask) && -+ !(rq->cmd_flags & REQ_COPY_USER)) { -+ res = -EINVAL; -+ goto out_free_bios; -+ } -+ -+ if (bw != NULL) -+ atomic_set(&bw->bios_inflight, bios); -+ -+ while (hbio != NULL) { -+ bio = hbio; -+ hbio = hbio->bi_next; -+ bio->bi_next = NULL; -+ -+ blk_queue_bounce(q, &bio); -+ -+ res = blk_rq_append_bio(q, rq, bio); -+ if (unlikely(res != 0)) { -+ bio->bi_next = hbio; -+ hbio = bio; -+ /* We can have one or more bios bounced */ -+ goto out_unmap_bios; -+ } -+ } -+ -+ res = 0; -+ -+ rq->buffer = NULL; -+out: -+ return res; -+ -+out_unmap_bios: -+ blk_rq_unmap_kern_sg(rq, res); -+ -+out_free_bios: -+ while (hbio != NULL) { -+ bio = hbio; -+ hbio = hbio->bi_next; -+ bio_put(bio); -+ } -+ goto out; -+} -+ -+/** -+ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC -+ * @rq: request to fill -+ * @sgl: area to map -+ * @nents: number of elements in @sgl -+ * @gfp: memory allocation flags -+ * -+ * Description: -+ * Data will be mapped directly if possible. Otherwise a bounce -+ * buffer will be used. -+ */ -+int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl, -+ int nents, gfp_t gfp) -+{ -+ int res; -+ -+ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp); -+ if (unlikely(res != 0)) { -+ struct blk_kern_sg_work *bw = NULL; -+ -+ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw, -+ gfp, rq->q->bounce_gfp | gfp); -+ if (unlikely(res != 0)) -+ goto out; -+ -+ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl, -+ bw->sg_table.nents, bw, gfp); -+ if (res != 0) { -+ blk_free_kern_sg_work(bw); -+ goto out; -+ } -+ } -+ -+ rq->buffer = NULL; -+ -+out: -+ return res; -+} -+EXPORT_SYMBOL(blk_rq_map_kern_sg); -+ -+/** -+ * blk_rq_unmap_kern_sg - unmap a request with kernel sg -+ * @rq: request to unmap -+ * @err: non-zero error code -+ * -+ * Description: -+ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called -+ * only in case of an error! -+ */ -+void blk_rq_unmap_kern_sg(struct request *rq, int err) -+{ -+ struct bio *bio = rq->bio; -+ -+ while (bio) { -+ struct bio *b = bio; -+ bio = bio->bi_next; -+ b->bi_end_io(b, err); -+ } -+ rq->bio = NULL; -+ -+ return; -+} -+EXPORT_SYMBOL(blk_rq_unmap_kern_sg); -+ - /** - * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage - * @q: request queue where request should be inserted - -=== modified file 'include/linux/blkdev.h' ---- old/include/linux/blkdev.h 2012-01-10 22:58:17 +0000 -+++ new/include/linux/blkdev.h 2012-01-10 23:01:21 +0000 -@@ -716,6 +718,9 @@ extern int blk_rq_map_kern(struct reques - extern int blk_rq_map_user_iov(struct request_queue *, struct request *, - struct rq_map_data *, struct sg_iovec *, int, - unsigned int, gfp_t); -+extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl, -+ int nents, gfp_t gfp); -+extern void blk_rq_unmap_kern_sg(struct request *rq, int err); - extern int blk_execute_rq(struct request_queue *, struct gendisk *, - struct request *, int); - extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, - -=== modified file 'include/linux/scatterlist.h' ---- old/include/linux/scatterlist.h 2012-01-10 22:58:17 +0000 -+++ new/include/linux/scatterlist.h 2012-01-10 23:01:21 +0000 -@@ -3,6 +3,7 @@ - - #include <asm/types.h> - #include <asm/scatterlist.h> -+#include <asm/kmap_types.h> - #include <linux/mm.h> - #include <linux/string.h> - #include <asm/io.h> -@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scatte - size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, - void *buf, size_t buflen); - -+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg, -+ int nents_to_copy, size_t copy_len, -+ enum km_type d_km_type, enum km_type s_km_type); -+ - /* - * Maximum number of entries that will be allocated in one piece, if - * a list larger than this is required then chaining will be utilized. - -=== modified file 'lib/scatterlist.c' ---- old/lib/scatterlist.c 2012-01-10 22:58:17 +0000 -+++ new/lib/scatterlist.c 2012-01-10 23:01:21 +0000 -@@ -517,3 +517,132 @@ size_t sg_copy_to_buffer(struct scatterl - return sg_copy_buffer(sgl, nents, buf, buflen, 1); - } - EXPORT_SYMBOL(sg_copy_to_buffer); -+ -+/* -+ * Can switch to the next dst_sg element, so, to copy to strictly only -+ * one dst_sg element, it must be either last in the chain, or -+ * copy_len == dst_sg->length. -+ */ -+static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len, -+ size_t *pdst_offs, struct scatterlist *src_sg, -+ size_t copy_len, -+ enum km_type d_km_type, enum km_type s_km_type) -+{ -+ int res = 0; -+ struct scatterlist *dst_sg; -+ size_t src_len, dst_len, src_offs, dst_offs; -+ struct page *src_page, *dst_page; -+ -+ dst_sg = *pdst_sg; -+ dst_len = *pdst_len; -+ dst_offs = *pdst_offs; -+ dst_page = sg_page(dst_sg); -+ -+ src_page = sg_page(src_sg); -+ src_len = src_sg->length; -+ src_offs = src_sg->offset; -+ -+ do { -+ void *saddr, *daddr; -+ size_t n; -+ -+ saddr = kmap_atomic(src_page + -+ (src_offs >> PAGE_SHIFT), s_km_type) + -+ (src_offs & ~PAGE_MASK); -+ daddr = kmap_atomic(dst_page + -+ (dst_offs >> PAGE_SHIFT), d_km_type) + -+ (dst_offs & ~PAGE_MASK); -+ -+ if (((src_offs & ~PAGE_MASK) == 0) && -+ ((dst_offs & ~PAGE_MASK) == 0) && -+ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) && -+ (copy_len >= PAGE_SIZE)) { -+ copy_page(daddr, saddr); -+ n = PAGE_SIZE; -+ } else { -+ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK), -+ PAGE_SIZE - (src_offs & ~PAGE_MASK)); -+ n = min(n, src_len); -+ n = min(n, dst_len); -+ n = min_t(size_t, n, copy_len); -+ memcpy(daddr, saddr, n); -+ } -+ dst_offs += n; -+ src_offs += n; -+ -+ kunmap_atomic(saddr, s_km_type); -+ kunmap_atomic(daddr, d_km_type); -+ -+ res += n; -+ copy_len -= n; -+ if (copy_len == 0) -+ goto out; -+ -+ src_len -= n; -+ dst_len -= n; -+ if (dst_len == 0) { -+ dst_sg = sg_next(dst_sg); -+ if (dst_sg == NULL) -+ goto out; -+ dst_page = sg_page(dst_sg); -+ dst_len = dst_sg->length; -+ dst_offs = dst_sg->offset; -+ } -+ } while (src_len > 0); -+ -+out: -+ *pdst_sg = dst_sg; -+ *pdst_len = dst_len; -+ *pdst_offs = dst_offs; -+ return res; -+} -+ -+/** -+ * sg_copy - copy one SG vector to another -+ * @dst_sg: destination SG -+ * @src_sg: source SG -+ * @nents_to_copy: maximum number of entries to copy -+ * @copy_len: maximum amount of data to copy. If 0, then copy all. -+ * @d_km_type: kmap_atomic type for the destination SG -+ * @s_km_type: kmap_atomic type for the source SG -+ * -+ * Description: -+ * Data from the source SG vector will be copied to the destination SG -+ * vector. End of the vectors will be determined by sg_next() returning -+ * NULL. Returns number of bytes copied. -+ */ -+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg, -+ int nents_to_copy, size_t copy_len, -+ enum km_type d_km_type, enum km_type s_km_type) -+{ -+ int res = 0; -+ size_t dst_len, dst_offs; -+ -+ if (copy_len == 0) -+ copy_len = 0x7FFFFFFF; /* copy all */ -+ -+ if (nents_to_copy == 0) -+ nents_to_copy = 0x7FFFFFFF; /* copy all */ -+ -+ dst_len = dst_sg->length; -+ dst_offs = dst_sg->offset; -+ -+ do { -+ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs, -+ src_sg, copy_len, d_km_type, s_km_type); -+ copy_len -= copied; -+ res += copied; -+ if ((copy_len == 0) || (dst_sg == NULL)) -+ goto out; -+ -+ nents_to_copy--; -+ if (nents_to_copy == 0) -+ goto out; -+ -+ src_sg = sg_next(src_sg); -+ } while (src_sg != NULL); -+ -+out: -+ return res; -+} -+EXPORT_SYMBOL(sg_copy); - -=== modified file 'include/linux/mm_types.h' ---- old/include/linux/mm_types.h 2012-01-10 22:58:17 +0000 -+++ new/include/linux/mm_types.h 2012-01-10 23:02:48 +0000 -@@ -149,6 +149,17 @@ struct page { - */ - void *shadow; - #endif -+ -+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) -+ /* -+ * Used to implement support for notification on zero-copy TCP transfer -+ * completion. It might look as not good to have this field here and -+ * it's better to have it in struct sk_buff, but it would make the code -+ * much more complicated and fragile, since all skb then would have to -+ * contain only pages with the same value in this field. -+ */ -+ void *net_priv; -+#endif - } - /* - * If another subsystem starts using the double word pairing for atomic - -=== modified file 'include/linux/net.h' ---- old/include/linux/net.h 2012-01-10 22:58:17 +0000 -+++ new/include/linux/net.h 2012-01-10 23:02:48 +0000 -@@ -61,6 +61,7 @@ typedef enum { - #include <linux/fcntl.h> /* For O_CLOEXEC and O_NONBLOCK */ - #include <linux/kmemcheck.h> - #include <linux/rcupdate.h> -+#include <linux/mm.h> - - struct poll_table_struct; - struct pipe_inode_info; -@@ -289,5 +290,44 @@ extern int kernel_sock_shutdown(struct s - MODULE_ALIAS("net-pf-" __stringify(pf) "-proto-" __stringify(proto) \ - "-type-" __stringify(type)) - -+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) -+/* Support for notification on zero-copy TCP transfer completion */ -+typedef void (*net_get_page_callback_t)(struct page *page); -+typedef void (*net_put_page_callback_t)(struct page *page); -+ -+extern net_get_page_callback_t net_get_page_callback; -+extern net_put_page_callback_t net_put_page_callback; -+ -+extern int net_set_get_put_page_callbacks( -+ net_get_page_callback_t get_callback, -+ net_put_page_callback_t put_callback); -+ -+/* -+ * See comment for net_set_get_put_page_callbacks() why those functions -+ * don't need any protection. -+ */ -+static inline void net_get_page(struct page *page) -+{ -+ if (page->net_priv != 0) -+ net_get_page_callback(page); -+ get_page(page); -+} -+static inline void net_put_page(struct page *page) -+{ -+ if (page->net_priv != 0) -+ net_put_page_callback(page); -+ put_page(page); -+} -+#else -+static inline void net_get_page(struct page *page) -+{ -+ get_page(page); -+} -+static inline void net_put_page(struct page *page) -+{ -+ put_page(page); -+} -+#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */ -+ - #endif /* __KERNEL__ */ - #endif /* _LINUX_NET_H */ - -=== modified file 'include/linux/skbuff.h' ---- old/include/linux/skbuff.h 2012-01-10 22:58:17 +0000 -+++ new/include/linux/skbuff.h 2012-01-10 23:15:31 +0000 -@@ -1712,7 +1712,7 @@ static inline struct page *skb_frag_page - */ - static inline void __skb_frag_ref(skb_frag_t *frag) - { -- get_page(skb_frag_page(frag)); -+ net_get_page(skb_frag_page(frag)); - } - - /** -@@ -1735,7 +1735,7 @@ static inline void skb_frag_ref(struct s - */ - static inline void __skb_frag_unref(skb_frag_t *frag) - { -- put_page(skb_frag_page(frag)); -+ net_put_page(skb_frag_page(frag)); - } - - /** - -=== modified file 'net/Kconfig' ---- old/net/Kconfig 2012-01-10 22:58:17 +0000 -+++ new/net/Kconfig 2012-01-10 23:02:48 +0000 -@@ -72,6 +72,18 @@ config INET - - Short answer: say Y. - -+config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION -+ bool "TCP/IP zero-copy transfer completion notification" -+ depends on INET -+ default SCST_ISCSI -+ ---help--- -+ Adds support for sending a notification upon completion of a -+ zero-copy TCP/IP transfer. This can speed up certain TCP/IP -+ software. Currently this is only used by the iSCSI target driver -+ iSCSI-SCST. -+ -+ If unsure, say N. -+ - if INET - source "net/ipv4/Kconfig" - source "net/ipv6/Kconfig" - -=== modified file 'net/core/skbuff.c' ---- old/net/core/skbuff.c 2012-01-10 22:58:17 +0000 -+++ new/net/core/skbuff.c 2012-01-10 23:02:48 +0000 -@@ -77,13 +77,13 @@ static struct kmem_cache *skbuff_fclone_ - static void sock_pipe_buf_release(struct pipe_inode_info *pipe, - struct pipe_buffer *buf) - { -- put_page(buf->page); -+ net_put_page(buf->page); - } - - static void sock_pipe_buf_get(struct pipe_inode_info *pipe, - struct pipe_buffer *buf) - { -- get_page(buf->page); -+ net_get_page(buf->page); - } - - static int sock_pipe_buf_steal(struct pipe_inode_info *pipe, -@@ -654,7 +654,7 @@ int skb_copy_ubufs(struct sk_buff *skb, - if (!page) { - while (head) { - struct page *next = (struct page *)head->private; -- put_page(head); -+ net_put_page(head); - head = next; - } - return -ENOMEM; -@@ -1493,7 +1493,7 @@ EXPORT_SYMBOL(skb_copy_bits); - */ - static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) - { -- put_page(spd->pages[i]); -+ net_put_page(spd->pages[i]); - } - - static inline struct page *linear_to_page(struct page *page, unsigned int *len, -@@ -1517,7 +1517,7 @@ new_page: - off = sk->sk_sndmsg_off; - mlen = PAGE_SIZE - off; - if (mlen < 64 && mlen < *len) { -- put_page(p); -+ net_put_page(p); - goto new_page; - } - -@@ -1527,7 +1527,7 @@ new_page: - memcpy(page_address(p) + off, page_address(page) + *offset, *len); - sk->sk_sndmsg_off += *len; - *offset = off; -- get_page(p); -+ net_get_page(p); - - return p; - } -@@ -1549,7 +1549,7 @@ static inline int spd_fill_page(struct s - if (!page) - return 1; - } else -- get_page(page); -+ net_get_page(page); - - spd->pages[spd->nr_pages] = page; - spd->partial[spd->nr_pages].len = *len; - -=== modified file 'net/ipv4/Makefile' ---- old/net/ipv4/Makefile 2012-01-10 22:58:17 +0000 -+++ new/net/ipv4/Makefile 2012-01-10 23:02:48 +0000 -@@ -48,6 +48,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o - obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o - obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o - obj-$(CONFIG_NETLABEL) += cipso_ipv4.o -+obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o - - obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ - xfrm4_output.o - -=== modified file 'net/ipv4/ip_output.c' ---- old/net/ipv4/ip_output.c 2012-01-10 22:58:17 +0000 -+++ new/net/ipv4/ip_output.c 2012-01-10 23:02:48 +0000 -@@ -1232,7 +1232,7 @@ ssize_t ip_append_page(struct sock *sk, - if (skb_can_coalesce(skb, i, page, offset)) { - skb_frag_size_add(&skb_shinfo(skb)->frags[i-1], len); - } else if (i < MAX_SKB_FRAGS) { -- get_page(page); -+ net_get_page(page); - skb_fill_page_desc(skb, i, page, offset, len); - } else { - err = -EMSGSIZE; - -=== modified file 'net/ipv4/tcp.c' ---- old/net/ipv4/tcp.c 2012-01-10 22:58:17 +0000 -+++ new/net/ipv4/tcp.c 2012-01-10 23:02:48 +0000 -@@ -815,7 +815,7 @@ new_segment: - if (can_coalesce) { - skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); - } else { -- get_page(page); -+ net_get_page(page); - skb_fill_page_desc(skb, i, page, offset, copy); - } - -@@ -1022,7 +1022,7 @@ new_segment: - goto new_segment; - } else if (page) { - if (off == PAGE_SIZE) { -- put_page(page); -+ net_put_page(page); - TCP_PAGE(sk) = page = NULL; - off = 0; - } -@@ -1062,9 +1062,9 @@ new_segment: - } else { - skb_fill_page_desc(skb, i, page, off, copy); - if (TCP_PAGE(sk)) { -- get_page(page); -+ net_get_page(page); - } else if (off + copy < PAGE_SIZE) { -- get_page(page); -+ net_get_page(page); - TCP_PAGE(sk) = page; - } - } - -=== added file 'net/ipv4/tcp_zero_copy.c' ---- old/net/ipv4/tcp_zero_copy.c 1970-01-01 00:00:00 +0000 -+++ new/net/ipv4/tcp_zero_copy.c 2012-01-10 23:43:22 +0000 -@@ -0,0 +1,50 @@ -+/* -+ * Support routines for TCP zero copy transmit -+ * -+ * Created by Vladislav Bolkhovitin -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ */ -+ -+#include <linux/export.h> -+#include <linux/skbuff.h> -+ -+net_get_page_callback_t net_get_page_callback __read_mostly; -+EXPORT_SYMBOL_GPL(net_get_page_callback); -+ -+net_put_page_callback_t net_put_page_callback __read_mostly; -+EXPORT_SYMBOL_GPL(net_put_page_callback); -+ -+/* -+ * Caller of this function must ensure that at the moment when it's called -+ * there are no pages in the system with net_priv field set to non-zero -+ * value. Hence, this function, as well as net_get_page() and net_put_page(), -+ * don't need any protection. -+ */ -+int net_set_get_put_page_callbacks( -+ net_get_page_callback_t get_callback, -+ net_put_page_callback_t put_callback) -+{ -+ int res = 0; -+ -+ if ((net_get_page_callback != NULL) && (get_callback != NULL) && -+ (net_get_page_callback != get_callback)) { -+ res = -EBUSY; -+ goto out; -+ } -+ -+ if ((net_put_page_callback != NULL) && (put_callback != NULL) && -+ (net_put_page_callback != put_callback)) { -+ res = -EBUSY; -+ goto out; -+ } -+ -+ net_get_page_callback = get_callback; -+ net_put_page_callback = put_callback; -+ -+out: -+ return res; -+} -+EXPORT_SYMBOL_GPL(net_set_get_put_page_callbacks); - -diff --git a/drivers/Kconfig b/drivers/Kconfig -index a2b902f..92e3d67 100644 ---- orig/linux-3.2/drivers/Kconfig -+++ linux-3.2/drivers/Kconfig -@@ -22,6 +22,8 @@ source "drivers/ide/Kconfig" - - source "drivers/scsi/Kconfig" - -+source "drivers/scst/Kconfig" -+ - source "drivers/ata/Kconfig" - - source "drivers/md/Kconfig" -diff --git a/drivers/Makefile b/drivers/Makefile -index b423bb1..f780114 100644 ---- orig/linux-3.2/drivers/Makefile -+++ linux-3.2/drivers/Makefile -@@ -115,5 +115,6 @@ obj-$(CONFIG_VLYNQ) += vlynq/ - obj-$(CONFIG_STAGING) += staging/ - obj-y += platform/ - obj-y += ieee802154/ -+obj-$(CONFIG_SCST) += scst/ - #common clk code - obj-y += clk/ -diff -uprN orig/linux-3.2/drivers/scst/Kconfig linux-3.2/drivers/scst/Kconfig ---- orig/linux-3.2/drivers/scst/Kconfig -+++ linux-3.2/drivers/scst/Kconfig -@@ -0,0 +1,255 @@ -+menu "SCSI target (SCST) support" -+ -+config SCST -+ tristate "SCSI target (SCST) support" -+ depends on SCSI -+ help -+ SCSI target (SCST) is designed to provide unified, consistent -+ interface between SCSI target drivers and Linux kernel and -+ simplify target drivers development as much as possible. Visit -+ http://scst.sourceforge.net for more info about it. -+ -+config SCST_DISK -+ tristate "SCSI target disk support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for disk device. -+ -+config SCST_TAPE -+ tristate "SCSI target tape support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for tape device. -+ -+config SCST_CDROM -+ tristate "SCSI target CDROM support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for CDROM device. -+ -+config SCST_MODISK -+ tristate "SCSI target MO disk support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for MO disk device. -+ -+config SCST_CHANGER -+ tristate "SCSI target changer support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for changer device. -+ -+config SCST_PROCESSOR -+ tristate "SCSI target processor support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for processor device. -+ -+config SCST_RAID -+ tristate "SCSI target storage array controller (RAID) support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST pass-through device handler for raid storage array controller (RAID) device. -+ -+config SCST_VDISK -+ tristate "SCSI target virtual disk and/or CDROM support" -+ default SCST -+ depends on SCSI && SCST -+ help -+ SCST device handler for virtual disk and/or CDROM device. -+ -+config SCST_USER -+ tristate "User-space SCSI target driver support" -+ default SCST -+ depends on SCSI && SCST && !HIGHMEM4G && !HIGHMEM64G -+ help -+ The SCST device handler scst_user allows to implement full-feature -+ SCSI target devices in user space. -+ -+ If unsure, say "N". -+ -+config SCST_STRICT_SERIALIZING -+ bool "Strict serialization" -+ depends on SCST -+ help -+ Enable strict SCSI command serialization. When enabled, SCST sends -+ all SCSI commands to the underlying SCSI device synchronously, one -+ after one. This makes task management more reliable, at the cost of -+ a performance penalty. This is most useful for stateful SCSI devices -+ like tapes, where the result of the execution of a command -+ depends on the device settings configured by previous commands. Disk -+ and RAID devices are stateless in most cases. The current SCSI core -+ in Linux doesn't allow to abort all commands reliably if they have -+ been sent asynchronously to a stateful device. -+ Enable this option if you use stateful device(s) and need as much -+ error recovery reliability as possible. -+ -+ If unsure, say "N". -+ -+config SCST_STRICT_SECURITY -+ bool "Strict security" -+ depends on SCST -+ help -+ Makes SCST clear (zero-fill) allocated data buffers. Note: this has a -+ significant performance penalty. -+ -+ If unsure, say "N". -+ -+config SCST_TEST_IO_IN_SIRQ -+ bool "Allow test I/O from soft-IRQ context" -+ depends on SCST -+ help -+ Allows SCST to submit selected SCSI commands (TUR and -+ READ/WRITE) from soft-IRQ context (tasklets). Enabling it will -+ decrease amount of context switches and slightly improve -+ performance. The goal of this option is to be able to measure -+ overhead of the context switches. See more info about it in -+ README.scst. -+ -+ WARNING! Improperly used, this option can lead you to a kernel crash! -+ -+ If unsure, say "N". -+ -+config SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING -+ bool "Send back UNKNOWN TASK when an already finished task is aborted" -+ depends on SCST -+ help -+ Controls which response is sent by SCST to the initiator in case -+ the initiator attempts to abort (ABORT TASK) an already finished -+ request. If this option is enabled, the response UNKNOWN TASK is -+ sent back to the initiator. However, some initiators, particularly -+ the VMware iSCSI initiator, interpret the UNKNOWN TASK response as -+ if the target got crazy and try to RESET it. Then sometimes the -+ initiator gets crazy itself. -+ -+ If unsure, say "N". -+ -+config SCST_USE_EXPECTED_VALUES -+ bool "Prefer initiator-supplied SCSI command attributes" -+ depends on SCST -+ help -+ When SCST receives a SCSI command from an initiator, such a SCSI -+ command has both data transfer length and direction attributes. -+ There are two possible sources for these attributes: either the -+ values computed by SCST from its internal command translation table -+ or the values supplied by the initiator. The former are used by -+ default because of security reasons. Invalid initiator-supplied -+ attributes can crash the target, especially in pass-through mode. -+ Only consider enabling this option when SCST logs the following -+ message: "Unknown opcode XX for YY. Should you update -+ scst_scsi_op_table?" and when the initiator complains. Please -+ report any unrecognized commands to scst-devel@lists.sourceforge.net. -+ -+ If unsure, say "N". -+ -+config SCST_EXTRACHECKS -+ bool "Extra consistency checks" -+ depends on SCST -+ help -+ Enable additional consistency checks in the SCSI middle level target -+ code. This may be helpful for SCST developers. Enable it if you have -+ any problems. -+ -+ If unsure, say "N". -+ -+config SCST_TRACING -+ bool "Tracing support" -+ depends on SCST -+ default y -+ help -+ Enable SCSI middle level tracing support. Tracing can be controlled -+ dynamically via sysfs interface. The traced information -+ is sent to the kernel log and may be very helpful when analyzing -+ the cause of a communication problem between initiator and target. -+ -+ If unsure, say "Y". -+ -+config SCST_DEBUG -+ bool "Debugging support" -+ depends on SCST -+ select DEBUG_BUGVERBOSE -+ help -+ Enables support for debugging SCST. This may be helpful for SCST -+ developers. -+ -+ If unsure, say "N". -+ -+config SCST_DEBUG_OOM -+ bool "Out-of-memory debugging support" -+ depends on SCST -+ help -+ Let SCST's internal memory allocation function -+ (scst_alloc_sg_entries()) fail about once in every 10000 calls, at -+ least if the flag __GFP_NOFAIL has not been set. This allows SCST -+ developers to test the behavior of SCST in out-of-memory conditions. -+ This may be helpful for SCST developers. -+ -+ If unsure, say "N". -+ -+config SCST_DEBUG_RETRY -+ bool "SCSI command retry debugging support" -+ depends on SCST -+ help -+ Let SCST's internal SCSI command transfer function -+ (scst_rdy_to_xfer()) fail about once in every 100 calls. This allows -+ SCST developers to test the behavior of SCST when SCSI queues fill -+ up. This may be helpful for SCST developers. -+ -+ If unsure, say "N". -+ -+config SCST_DEBUG_SN -+ bool "SCSI sequence number debugging support" -+ depends on SCST -+ help -+ Allows to test SCSI command ordering via sequence numbers by -+ randomly changing the type of SCSI commands into -+ SCST_CMD_QUEUE_ORDERED, SCST_CMD_QUEUE_HEAD_OF_QUEUE or -+ SCST_CMD_QUEUE_SIMPLE for about one in 300 SCSI commands. -+ This may be helpful for SCST developers. -+ -+ If unsure, say "N". -+ -+config SCST_DEBUG_TM -+ bool "Task management debugging support" -+ depends on SCST_DEBUG -+ help -+ Enables support for debugging of SCST's task management functions. -+ When enabled, some of the commands on LUN 0 in the default access -+ control group will be delayed for about 60 seconds. This will -+ cause the remote initiator send SCSI task management functions, -+ e.g. ABORT TASK and TARGET RESET. -+ -+ If unsure, say "N". -+ -+config SCST_TM_DBG_GO_OFFLINE -+ bool "Let devices become completely unresponsive" -+ depends on SCST_DEBUG_TM -+ help -+ Enable this option if you want that the device eventually becomes -+ completely unresponsive. When disabled, the device will receive -+ ABORT and RESET commands. -+ -+config SCST_MEASURE_LATENCY -+ bool "Commands processing latency measurement facility" -+ depends on SCST -+ help -+ This option enables commands processing latency measurement -+ facility in SCST. It will provide in the sysfs interface -+ average commands processing latency statistics. You can clear -+ already measured results by writing 0 in the corresponding sysfs file. -+ Note, you need a non-preemtible kernel to have correct results. -+ -+ If unsure, say "N". -+ -+source "drivers/scst/iscsi-scst/Kconfig" -+source "drivers/scst/scst_local/Kconfig" -+source "drivers/scst/srpt/Kconfig" -+ -+endmenu -diff -uprN orig/linux-3.2/drivers/scst/Makefile linux-3.2/drivers/scst/Makefile ---- orig/linux-3.2/drivers/scst/Makefile -+++ linux-3.2/drivers/scst/Makefile -@@ -0,0 +1,13 @@ -+ccflags-y += -Wno-unused-parameter -+ -+scst-y += scst_main.o -+scst-y += scst_pres.o -+scst-y += scst_targ.o -+scst-y += scst_lib.o -+scst-y += scst_sysfs.o -+scst-y += scst_mem.o -+scst-y += scst_tg.o -+scst-y += scst_debug.o -+ -+obj-$(CONFIG_SCST) += scst.o dev_handlers/ iscsi-scst/ qla2xxx-target/ \ -+ srpt/ scst_local/ -diff -uprN orig/linux-3.2/include/scst/scst.h linux-3.2/include/scst/scst.h ---- orig/linux-3.2/include/scst/scst.h -+++ linux-3.2/include/scst/scst.h -@@ -0,0 +1,3867 @@ -+/* -+ * include/scst.h -+ * -+ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net> -+ * Copyright (C) 2004 - 2005 Leonid Stoljar -+ * Copyright (C) 2007 - 2010 ID7 Ltd. -+ * Copyright (C) 2010 - 2011 SCST Ltd. -+ * Copyright (C) 2010 - 2011 Bart Van Assche <bvanassche@acm.org>. -+ * -+ * Main SCSI target mid-level include file. -+ * -+ * 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, version 2 -+ * of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __SCST_H -+#define __SCST_H -+ -+#include <linux/types.h> -+#include <linux/blkdev.h> -+#include <linux/interrupt.h> -+#include <linux/wait.h> -+#include <linux/cpumask.h> -+ -+ -+#include <scsi/scsi_cmnd.h> -+#include <scsi/scsi_device.h> -+#include <scsi/scsi_eh.h> -+#include <scsi/scsi.h> -+ -+#include <scst/scst_const.h> -+ -+#include <scst/scst_sgv.h> -+ -+#define SCST_INTERFACE_VERSION \ -+ SCST_VERSION_STRING "$Revision: 3992 $" SCST_CONST_VERSION -+ -+#define SCST_LOCAL_NAME "scst_local" -+ -+/************************************************************* -+ ** States of command processing state machine. At first, -+ ** "active" states, then - "passive" ones. This is to have -+ ** more efficient generated code of the corresponding -+ ** "switch" statements. -+ *************************************************************/ -+ -+/* Dev handler's parse() is going to be called */ -+#define SCST_CMD_STATE_PARSE 0 -+ -+/* Allocation of the cmd's data buffer */ -+#define SCST_CMD_STATE_PREPARE_SPACE 1 -+ -+/* Calling preprocessing_done() */ -+#define SCST_CMD_STATE_PREPROCESSING_DONE 2 -+ -+/* Target driver's rdy_to_xfer() is going to be called */ -+#define SCST_CMD_STATE_RDY_TO_XFER 3 -+ -+/* Target driver's pre_exec() is going to be called */ -+#define SCST_CMD_STATE_TGT_PRE_EXEC 4 -+ -+/* Cmd is going to be sent for execution */ -+#define SCST_CMD_STATE_SEND_FOR_EXEC 5 -+ -+/* Internal post-exec checks */ -+#define SCST_CMD_STATE_PRE_DEV_DONE 6 -+ -+/* Internal MODE SELECT pages related checks */ -+#define SCST_CMD_STATE_MODE_SELECT_CHECKS 7 -+ -+/* Dev handler's dev_done() is going to be called */ -+#define SCST_CMD_STATE_DEV_DONE 8 -+ -+/* Checks before target driver's xmit_response() is called */ -+#define SCST_CMD_STATE_PRE_XMIT_RESP 9 -+ -+/* Target driver's xmit_response() is going to be called */ -+#define SCST_CMD_STATE_XMIT_RESP 10 -+ -+/* Cmd finished */ -+#define SCST_CMD_STATE_FINISHED 11 -+ -+/* Internal cmd finished */ -+#define SCST_CMD_STATE_FINISHED_INTERNAL 12 -+ -+#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED_INTERNAL+100) -+ -+/* A cmd is created, but scst_cmd_init_done() not called */ -+#define SCST_CMD_STATE_INIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+1) -+ -+/* LUN translation (cmd->tgt_dev assignment) */ -+#define SCST_CMD_STATE_INIT (SCST_CMD_STATE_LAST_ACTIVE+2) -+ -+/* Waiting for scst_restart_cmd() */ -+#define SCST_CMD_STATE_PREPROCESSING_DONE_CALLED (SCST_CMD_STATE_LAST_ACTIVE+3) -+ -+/* Waiting for data from the initiator (until scst_rx_data() called) */ -+#define SCST_CMD_STATE_DATA_WAIT (SCST_CMD_STATE_LAST_ACTIVE+4) -+ -+/* -+ * Cmd is ready for exec (after check if its device is blocked or should -+ * be blocked) -+ */ -+#define SCST_CMD_STATE_START_EXEC (SCST_CMD_STATE_LAST_ACTIVE+5) -+ -+/* Cmd is being checked if it should be executed locally */ -+#define SCST_CMD_STATE_LOCAL_EXEC (SCST_CMD_STATE_LAST_ACTIVE+6) -+ -+/* Cmd is ready for execution */ -+#define SCST_CMD_STATE_REAL_EXEC (SCST_CMD_STATE_LAST_ACTIVE+7) -+ -+/* Waiting for CDB's execution finish */ -+#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+8) -+ -+/* Waiting for response's transmission finish */ -+#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+9) -+ -+/************************************************************* -+ * Can be returned instead of cmd's state by dev handlers' -+ * functions, if the command's state should be set by default -+ *************************************************************/ -+#define SCST_CMD_STATE_DEFAULT 500 -+ -+/************************************************************* -+ * Can be returned instead of cmd's state by dev handlers' -+ * functions, if it is impossible to complete requested -+ * task in atomic context. The cmd will be restarted in thread -+ * context. -+ *************************************************************/ -+#define SCST_CMD_STATE_NEED_THREAD_CTX 1000 -+ -+/************************************************************* -+ * Can be returned instead of cmd's state by dev handlers' -+ * parse function, if the cmd processing should be stopped -+ * for now. The cmd will be restarted by dev handlers itself. -+ *************************************************************/ -+#define SCST_CMD_STATE_STOP 1001 -+ -+/************************************************************* -+ ** States of mgmt command processing state machine -+ *************************************************************/ -+ -+/* LUN translation (mcmd->tgt_dev assignment) */ -+#define SCST_MCMD_STATE_INIT 0 -+ -+/* Mgmt cmd is being processed */ -+#define SCST_MCMD_STATE_EXEC 1 -+ -+/* Waiting for affected commands done */ -+#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE 2 -+ -+/* Post actions when affected commands done */ -+#define SCST_MCMD_STATE_AFFECTED_CMDS_DONE 3 -+ -+/* Waiting for affected local commands finished */ -+#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED 4 -+ -+/* Target driver's task_mgmt_fn_done() is going to be called */ -+#define SCST_MCMD_STATE_DONE 5 -+ -+/* The mcmd finished */ -+#define SCST_MCMD_STATE_FINISHED 6 -+ -+/************************************************************* -+ ** Constants for "atomic" parameter of SCST's functions -+ *************************************************************/ -+#define SCST_NON_ATOMIC 0 -+#define SCST_ATOMIC 1 -+ -+/************************************************************* -+ ** Values for pref_context parameter of scst_cmd_init_done(), -+ ** scst_rx_data(), scst_restart_cmd(), scst_tgt_cmd_done() -+ ** and scst_cmd_done() -+ *************************************************************/ -+ -+enum scst_exec_context { -+ /* -+ * Direct cmd's processing (i.e. regular function calls in the current -+ * context) sleeping is not allowed -+ */ -+ SCST_CONTEXT_DIRECT_ATOMIC, -+ -+ /* -+ * Direct cmd's processing (i.e. regular function calls in the current -+ * context), sleeping is allowed, no restrictions -+ */ -+ SCST_CONTEXT_DIRECT, -+ -+ /* Tasklet or thread context required for cmd's processing */ -+ SCST_CONTEXT_TASKLET, -+ -+ /* Thread context required for cmd's processing */ -+ SCST_CONTEXT_THREAD, -+ -+ /* -+ * Context is the same as it was in previous call of the corresponding -+ * callback. For example, if dev handler's exec() does sync. data -+ * reading this value should be used for scst_cmd_done(). The same is -+ * true if scst_tgt_cmd_done() called directly from target driver's -+ * xmit_response(). Not allowed in scst_cmd_init_done() and -+ * scst_cmd_init_stage1_done(). -+ */ -+ SCST_CONTEXT_SAME -+}; -+ -+/************************************************************* -+ ** Values for status parameter of scst_rx_data() -+ *************************************************************/ -+ -+/* Success */ -+#define SCST_RX_STATUS_SUCCESS 0 -+ -+/* -+ * Data receiving finished with error, so set the sense and -+ * finish the command, including xmit_response() call -+ */ -+#define SCST_RX_STATUS_ERROR 1 -+ -+/* -+ * Data receiving finished with error and the sense is set, -+ * so finish the command, including xmit_response() call -+ */ -+#define SCST_RX_STATUS_ERROR_SENSE_SET 2 -+ -+/* -+ * Data receiving finished with fatal error, so finish the command, -+ * but don't call xmit_response() -+ */ -+#define SCST_RX_STATUS_ERROR_FATAL 3 -+ -+/************************************************************* -+ ** Values for status parameter of scst_restart_cmd() -+ *************************************************************/ -+ -+/* Success */ -+#define SCST_PREPROCESS_STATUS_SUCCESS 0 -+ -+/* -+ * Command's processing finished with error, so set the sense and -+ * finish the command, including xmit_response() call -+ */ -+#define SCST_PREPROCESS_STATUS_ERROR 1 -+ -+/* -+ * Command's processing finished with error and the sense is set, -+ * so finish the command, including xmit_response() call -+ */ -+#define SCST_PREPROCESS_STATUS_ERROR_SENSE_SET 2 -+ -+/* -+ * Command's processing finished with fatal error, so finish the command, -+ * but don't call xmit_response() -+ */ -+#define SCST_PREPROCESS_STATUS_ERROR_FATAL 3 -+ -+/************************************************************* -+ ** Values for AEN functions -+ *************************************************************/ -+ -+/* -+ * SCSI Asynchronous Event. Parameter contains SCSI sense -+ * (Unit Attention). AENs generated only for 2 the following UAs: -+ * CAPACITY DATA HAS CHANGED and REPORTED LUNS DATA HAS CHANGED. -+ * Other UAs reported regularly as CHECK CONDITION status, -+ * because it doesn't look safe to report them using AENs, since -+ * reporting using AENs opens delivery race windows even in case of -+ * untagged commands. -+ */ -+#define SCST_AEN_SCSI 0 -+ -+/* -+ * Notifies that CPU affinity mask on the corresponding session changed -+ */ -+#define SCST_AEN_CPU_MASK_CHANGED 1 -+ -+/************************************************************* -+ ** Allowed return/status codes for report_aen() callback and -+ ** scst_set_aen_delivery_status() function -+ *************************************************************/ -+ -+/* Success */ -+#define SCST_AEN_RES_SUCCESS 0 -+ -+/* Not supported */ -+#define SCST_AEN_RES_NOT_SUPPORTED -1 -+ -+/* Failure */ -+#define SCST_AEN_RES_FAILED -2 -+ -+/************************************************************* -+ ** Allowed return codes for xmit_response(), rdy_to_xfer() -+ *************************************************************/ -+ -+/* Success */ -+#define SCST_TGT_RES_SUCCESS 0 -+ -+/* Internal device queue is full, retry again later */ -+#define SCST_TGT_RES_QUEUE_FULL -1 -+ -+/* -+ * It is impossible to complete requested task in atomic context. -+ * The cmd will be restarted in thread context. -+ */ -+#define SCST_TGT_RES_NEED_THREAD_CTX -2 -+ -+/* -+ * Fatal error, if returned by xmit_response() the cmd will -+ * be destroyed, if by any other function, xmit_response() -+ * will be called with HARDWARE ERROR sense data -+ */ -+#define SCST_TGT_RES_FATAL_ERROR -3 -+ -+/************************************************************* -+ ** Return codes for dev handler's exec() -+ *************************************************************/ -+ -+/* The cmd is done, go to other ones */ -+#define SCST_EXEC_COMPLETED 0 -+ -+/* The cmd should be sent to SCSI mid-level */ -+#define SCST_EXEC_NOT_COMPLETED 1 -+ -+/************************************************************* -+ ** Additional return code for dev handler's task_mgmt_fn() -+ *************************************************************/ -+ -+/* Regular standard actions for the command should be done */ -+#define SCST_DEV_TM_NOT_COMPLETED 1 -+ -+/************************************************************* -+ ** Session initialization phases -+ *************************************************************/ -+ -+/* Set if session is being initialized */ -+#define SCST_SESS_IPH_INITING 0 -+ -+/* Set if the session is successfully initialized */ -+#define SCST_SESS_IPH_SUCCESS 1 -+ -+/* Set if the session initialization failed */ -+#define SCST_SESS_IPH_FAILED 2 -+ -+/* Set if session is initialized and ready */ -+#define SCST_SESS_IPH_READY 3 -+ -+/************************************************************* -+ ** Session shutdown phases -+ *************************************************************/ -+ -+/* Set if session is initialized and ready */ -+#define SCST_SESS_SPH_READY 0 -+ -+/* Set if session is shutting down */ -+#define SCST_SESS_SPH_SHUTDOWN 1 -+ -+/* Set if session is shutting down */ -+#define SCST_SESS_SPH_UNREG_DONE_CALLING 2 -+ -+/************************************************************* -+ ** Session's async (atomic) flags -+ *************************************************************/ -+ -+/* Set if the sess's hw pending work is scheduled */ -+#define SCST_SESS_HW_PENDING_WORK_SCHEDULED 0 -+ -+/************************************************************* -+ ** Cmd's async (atomic) flags -+ *************************************************************/ -+ -+/* Set if the cmd is aborted and ABORTED sense will be sent as the result */ -+#define SCST_CMD_ABORTED 0 -+ -+/* Set if the cmd is aborted by other initiator */ -+#define SCST_CMD_ABORTED_OTHER 1 -+ -+/* Set if no response should be sent to the target about this cmd */ -+#define SCST_CMD_NO_RESP 2 -+ -+/* Set if the cmd is dead and can be destroyed at any time */ -+#define SCST_CMD_CAN_BE_DESTROYED 3 -+ -+/* -+ * Set if the cmd's device has TAS flag set. Used only when aborted by -+ * other initiator. -+ */ -+#define SCST_CMD_DEVICE_TAS 4 -+ -+/************************************************************* -+ ** Tgt_dev's async. flags (tgt_dev_flags) -+ *************************************************************/ -+ -+/* Set if tgt_dev has Unit Attention sense */ -+#define SCST_TGT_DEV_UA_PENDING 0 -+ -+/* Set if tgt_dev is RESERVED by another session */ -+#define SCST_TGT_DEV_RESERVED 1 -+ -+/* Set if the corresponding context should be atomic */ -+#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5 -+#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 6 -+ -+#define SCST_TGT_DEV_CLUST_POOL 11 -+ -+/************************************************************* -+ ** I/O grouping types. Changing them don't forget to change -+ ** the corresponding *_STR values in scst_const.h! -+ *************************************************************/ -+ -+/* -+ * All initiators with the same name connected to this group will have -+ * shared IO context, for each name own context. All initiators with -+ * different names will have own IO context. -+ */ -+#define SCST_IO_GROUPING_AUTO 0 -+ -+/* All initiators connected to this group will have shared IO context */ -+#define SCST_IO_GROUPING_THIS_GROUP_ONLY -1 -+ -+/* Each initiator connected to this group will have own IO context */ -+#define SCST_IO_GROUPING_NEVER -2 -+ -+/************************************************************* -+ ** Kernel cache creation helper -+ *************************************************************/ -+ -+/************************************************************* -+ ** Valid_mask constants for scst_analyze_sense() -+ *************************************************************/ -+ -+#define SCST_SENSE_KEY_VALID 1 -+#define SCST_SENSE_ASC_VALID 2 -+#define SCST_SENSE_ASCQ_VALID 4 -+ -+#define SCST_SENSE_ASCx_VALID (SCST_SENSE_ASC_VALID | \ -+ SCST_SENSE_ASCQ_VALID) -+ -+#define SCST_SENSE_ALL_VALID (SCST_SENSE_KEY_VALID | \ -+ SCST_SENSE_ASC_VALID | \ -+ SCST_SENSE_ASCQ_VALID) -+ -+/************************************************************* -+ * TYPES -+ *************************************************************/ -+ -+struct scst_tgt; -+struct scst_session; -+struct scst_cmd; -+struct scst_mgmt_cmd; -+struct scst_device; -+struct scst_tgt_dev; -+struct scst_dev_type; -+struct scst_acg; -+struct scst_acg_dev; -+struct scst_acn; -+struct scst_aen; -+ -+/* -+ * SCST uses 64-bit numbers to represent LUN's internally. The value -+ * NO_SUCH_LUN is guaranteed to be different of every valid LUN. -+ */ -+#define NO_SUCH_LUN ((uint64_t)-1) -+ -+typedef enum dma_data_direction scst_data_direction; -+ -+/* -+ * SCST target template: defines target driver's parameters and callback -+ * functions. -+ * -+ * MUST HAVEs define functions that are expected to be defined in order to -+ * work. OPTIONAL says that there is a choice. -+ */ -+struct scst_tgt_template { -+ /* public: */ -+ -+ /* -+ * SG tablesize allows to check whether scatter/gather can be used -+ * or not. -+ */ -+ int sg_tablesize; -+ -+ /* -+ * True, if this target adapter uses unchecked DMA onto an ISA bus. -+ */ -+ unsigned unchecked_isa_dma:1; -+ -+ /* -+ * True, if this target adapter can benefit from using SG-vector -+ * clustering (i.e. smaller number of segments). -+ */ -+ unsigned use_clustering:1; -+ -+ /* -+ * True, if this target adapter doesn't support SG-vector clustering -+ */ -+ unsigned no_clustering:1; -+ -+ /* -+ * True, if corresponding function supports execution in -+ * the atomic (non-sleeping) context -+ */ -+ unsigned xmit_response_atomic:1; -+ unsigned rdy_to_xfer_atomic:1; -+ -+ /* True, if this target doesn't need "enabled" attribute */ -+ unsigned enabled_attr_not_needed:1; -+ -+ /* -+ * True if SCST should report that it supports ACA although it does -+ * not yet support ACA. Necessary for the IBM virtual SCSI target -+ * driver. -+ */ -+ unsigned fake_aca:1; -+ -+ /* -+ * Preferred SCSI LUN addressing method. -+ */ -+ enum scst_lun_addr_method preferred_addr_method; -+ -+ /* -+ * The maximum time in seconds cmd can stay inside the target -+ * hardware, i.e. after rdy_to_xfer() and xmit_response(), before -+ * on_hw_pending_cmd_timeout() will be called, if defined. -+ * -+ * In the current implementation a cmd will be aborted in time t -+ * max_hw_pending_time <= t < 2*max_hw_pending_time. -+ */ -+ int max_hw_pending_time; -+ -+ /* -+ * This function is equivalent to the SCSI -+ * queuecommand. The target should transmit the response -+ * buffer and the status in the scst_cmd struct. -+ * The expectation is that this executing this command is NON-BLOCKING. -+ * If it is blocking, consider to set threads_num to some none 0 number. -+ * -+ * After the response is actually transmitted, the target -+ * should call the scst_tgt_cmd_done() function of the -+ * mid-level, which will allow it to free up the command. -+ * Returns one of the SCST_TGT_RES_* constants. -+ * -+ * Pay attention to "atomic" attribute of the cmd, which can be get -+ * by scst_cmd_atomic(): it is true if the function called in the -+ * atomic (non-sleeping) context. -+ * -+ * MUST HAVE -+ */ -+ int (*xmit_response) (struct scst_cmd *cmd); -+ -+ /* -+ * This function informs the driver that data -+ * buffer corresponding to the said command have now been -+ * allocated and it is OK to receive data for this command. -+ * This function is necessary because a SCSI target does not -+ * have any control over the commands it receives. Most lower -+ * level protocols have a corresponding function which informs -+ * the initiator that buffers have been allocated e.g., XFER_ -+ * RDY in Fibre Channel. After the data is actually received -+ * the low-level driver needs to call scst_rx_data() in order to -+ * continue processing this command. -+ * Returns one of the SCST_TGT_RES_* constants. -+ * -+ * This command is expected to be NON-BLOCKING. -+ * If it is blocking, consider to set threads_num to some none 0 number. -+ * -+ * Pay attention to "atomic" attribute of the cmd, which can be get -+ * by scst_cmd_atomic(): it is true if the function called in the -+ * atomic (non-sleeping) context. -+ * -+ * OPTIONAL -+ */ -+ int (*rdy_to_xfer) (struct scst_cmd *cmd); -+ -+ /* -+ * Called if cmd stays inside the target hardware, i.e. after -+ * rdy_to_xfer() and xmit_response(), more than max_hw_pending_time -+ * time. The target driver supposed to cleanup this command and -+ * resume cmd's processing. -+ * -+ * OPTIONAL -+ */ -+ void (*on_hw_pending_cmd_timeout) (struct scst_cmd *cmd); -+ -+ /* -+ * Called to notify the driver that the command is about to be freed. -+ * Necessary, because for aborted commands xmit_response() could not -+ * be called. Could be called on IRQ context. -+ * -+ * OPTIONAL -+ */ -+ void (*on_free_cmd) (struct scst_cmd *cmd); -+ -+ /* -+ * This function allows target driver to handle data buffer -+ * allocations on its own. -+ * -+ * Target driver doesn't have to always allocate buffer in this -+ * function, but if it decide to do it, it must check that -+ * scst_cmd_get_data_buff_alloced() returns 0, otherwise to avoid -+ * double buffer allocation and memory leaks alloc_data_buf() shall -+ * fail. -+ * -+ * Shall return 0 in case of success or < 0 (preferably -ENOMEM) -+ * in case of error, or > 0 if the regular SCST allocation should be -+ * done. In case of returning successfully, -+ * scst_cmd->tgt_data_buf_alloced will be set by SCST. -+ * -+ * It is possible that both target driver and dev handler request own -+ * memory allocation. In this case, data will be memcpy() between -+ * buffers, where necessary. -+ * -+ * If allocation in atomic context - cf. scst_cmd_atomic() - is not -+ * desired or fails and consequently < 0 is returned, this function -+ * will be re-called in thread context. -+ * -+ * Please note that the driver will have to handle itself all relevant -+ * details such as scatterlist setup, highmem, freeing the allocated -+ * memory, etc. -+ * -+ * OPTIONAL. -+ */ -+ int (*alloc_data_buf) (struct scst_cmd *cmd); -+ -+ /* -+ * This function informs the driver that data -+ * buffer corresponding to the said command have now been -+ * allocated and other preprocessing tasks have been done. -+ * A target driver could need to do some actions at this stage. -+ * After the target driver done the needed actions, it shall call -+ * scst_restart_cmd() in order to continue processing this command. -+ * In case of preliminary the command completion, this function will -+ * also be called before xmit_response(). -+ * -+ * Called only if the cmd is queued using scst_cmd_init_stage1_done() -+ * instead of scst_cmd_init_done(). -+ * -+ * Returns void, the result is expected to be returned using -+ * scst_restart_cmd(). -+ * -+ * This command is expected to be NON-BLOCKING. -+ * If it is blocking, consider to set threads_num to some none 0 number. -+ * -+ * Pay attention to "atomic" attribute of the cmd, which can be get -+ * by scst_cmd_atomic(): it is true if the function called in the -+ * atomic (non-sleeping) context. -+ * -+ * OPTIONAL. -+ */ -+ void (*preprocessing_done) (struct scst_cmd *cmd); -+ -+ /* -+ * This function informs the driver that the said command is about -+ * to be executed. -+ * -+ * Returns one of the SCST_PREPROCESS_* constants. -+ * -+ * This command is expected to be NON-BLOCKING. -+ * If it is blocking, consider to set threads_num to some none 0 number. -+ * -+ * OPTIONAL -+ */ -+ int (*pre_exec) (struct scst_cmd *cmd); -+ -+ /* -+ * This function informs the driver that all affected by the -+ * corresponding task management function commands have beed completed. -+ * No return value expected. -+ * -+ * This function is expected to be NON-BLOCKING. -+ * -+ * Called without any locks held from a thread context. -+ * -+ * OPTIONAL -+ */ -+ void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd); -+ -+ /* -+ * This function informs the driver that the corresponding task -+ * management function has been completed, i.e. all the corresponding -+ * commands completed and freed. No return value expected. -+ * -+ * This function is expected to be NON-BLOCKING. -+ * -+ * Called without any locks held from a thread context. -+ * -+ * MUST HAVE if the target supports task management. -+ */ -+ void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd); -+ -+ /* -+ * Called to notify target driver that the command is being aborted. -+ * If target driver wants to redirect processing to some outside -+ * processing, it should get it using scst_cmd_get(). -+ * -+ * OPTIONAL -+ */ -+ void (*on_abort_cmd) (struct scst_cmd *cmd); -+ -+ /* -+ * This function should detect the target adapters that -+ * are present in the system. The function should return a value -+ * >= 0 to signify the number of detected target adapters. -+ * A negative value should be returned whenever there is -+ * an error. -+ * -+ * MUST HAVE -+ */ -+ int (*detect) (struct scst_tgt_template *tgt_template); -+ -+ /* -+ * This function should free up the resources allocated to the device. -+ * The function should return 0 to indicate successful release -+ * or a negative value if there are some issues with the release. -+ * In the current version the return value is ignored. -+ * -+ * MUST HAVE -+ */ -+ int (*release) (struct scst_tgt *tgt); -+ -+ /* -+ * This function is used for Asynchronous Event Notifications. -+ * -+ * Returns one of the SCST_AEN_RES_* constants. -+ * After AEN is sent, target driver must call scst_aen_done() and, -+ * optionally, scst_set_aen_delivery_status(). -+ * -+ * This function is expected to be NON-BLOCKING, but can sleep. -+ * -+ * This function must be prepared to handle AENs between calls for the -+ * corresponding session of scst_unregister_session() and -+ * unreg_done_fn() callback called or before scst_unregister_session() -+ * returned, if its called in the blocking mode. AENs for such sessions -+ * should be ignored. -+ * -+ * MUST HAVE, if low-level protocol supports AENs. -+ */ -+ int (*report_aen) (struct scst_aen *aen); -+ -+ /* -+ * This function returns in tr_id the corresponding to sess initiator -+ * port TransportID in the form as it's used by PR commands, see -+ * "Transport Identifiers" in SPC. Space for the initiator port -+ * TransportID must be allocated via kmalloc(). Caller supposed to -+ * kfree() it, when it isn't needed anymore. -+ * -+ * If sess is NULL, this function must return TransportID PROTOCOL -+ * IDENTIFIER for the requested target. -+ * -+ * Returns 0 on success or negative error code otherwise. -+ * -+ * SHOULD HAVE, because it's required for Persistent Reservations. -+ */ -+ int (*get_initiator_port_transport_id) (struct scst_tgt *tgt, -+ struct scst_session *sess, uint8_t **transport_id); -+ -+ /* -+ * This function allows to enable or disable particular target. -+ * A disabled target doesn't receive and process any SCSI commands. -+ * -+ * SHOULD HAVE to avoid race when there are connected initiators, -+ * while target not yet completed the initial configuration. In this -+ * case the too early connected initiators would see not those devices, -+ * which they intended to see. -+ * -+ * If you are sure your target driver doesn't need enabling target, -+ * you should set enabled_attr_not_needed in 1. -+ */ -+ int (*enable_target) (struct scst_tgt *tgt, bool enable); -+ -+ /* -+ * This function shows if particular target is enabled or not. -+ * -+ * SHOULD HAVE, see above why. -+ */ -+ bool (*is_target_enabled) (struct scst_tgt *tgt); -+ -+ /* -+ * This function adds a virtual target. -+ * -+ * If both add_target and del_target callbacks defined, then this -+ * target driver supposed to support virtual targets. In this case -+ * an "mgmt" entry will be created in the sysfs root for this driver. -+ * The "mgmt" entry will support 2 commands: "add_target" and -+ * "del_target", for which the corresponding callbacks will be called. -+ * Also target driver can define own commands for the "mgmt" entry, see -+ * mgmt_cmd and mgmt_cmd_help below. -+ * -+ * This approach allows uniform targets management to simplify external -+ * management tools like scstadmin. See README for more details. -+ * -+ * Either both add_target and del_target must be defined, or none. -+ * -+ * MUST HAVE if virtual targets are supported. -+ */ -+ ssize_t (*add_target) (const char *target_name, char *params); -+ -+ /* -+ * This function deletes a virtual target. See comment for add_target -+ * above. -+ * -+ * MUST HAVE if virtual targets are supported. -+ */ -+ ssize_t (*del_target) (const char *target_name); -+ -+ /* -+ * This function called if not "add_target" or "del_target" command is -+ * sent to the mgmt entry (see comment for add_target above). In this -+ * case the command passed to this function as is in a string form. -+ * -+ * OPTIONAL. -+ */ -+ ssize_t (*mgmt_cmd) (char *cmd); -+ -+ /* -+ * Should return physical transport version. Used in the corresponding -+ * INQUIRY version descriptor. See SPC for the list of available codes. -+ * -+ * OPTIONAL -+ */ -+ uint16_t (*get_phys_transport_version) (struct scst_tgt *tgt); -+ -+ /* -+ * Should return SCSI transport version. Used in the corresponding -+ * INQUIRY version descriptor. See SPC for the list of available codes. -+ * -+ * OPTIONAL -+ */ -+ uint16_t (*get_scsi_transport_version) (struct scst_tgt *tgt); -+ -+ /* -+ * Name of the template. Must be unique to identify -+ * the template. MUST HAVE -+ */ -+ const char name[SCST_MAX_NAME]; -+ -+ /* -+ * Number of additional threads to the pool of dedicated threads. -+ * Used if xmit_response() or rdy_to_xfer() is blocking. -+ * It is the target driver's duty to ensure that not more, than that -+ * number of threads, are blocked in those functions at any time. -+ */ -+ int threads_num; -+ -+ /* Optional default log flags */ -+ const unsigned long default_trace_flags; -+ -+ /* Optional pointer to trace flags */ -+ unsigned long *trace_flags; -+ -+ /* Optional local trace table */ -+ struct scst_trace_log *trace_tbl; -+ -+ /* Optional local trace table help string */ -+ const char *trace_tbl_help; -+ -+ /* sysfs attributes, if any */ -+ const struct attribute **tgtt_attrs; -+ -+ /* sysfs target attributes, if any */ -+ const struct attribute **tgt_attrs; -+ -+ /* sysfs session attributes, if any */ -+ const struct attribute **sess_attrs; -+ -+ /* Optional help string for mgmt_cmd commands */ -+ const char *mgmt_cmd_help; -+ -+ /* List of parameters for add_target command, if any */ -+ const char *add_target_parameters; -+ -+ /* -+ * List of optional, i.e. which could be added by add_attribute command -+ * and deleted by del_attribute command, sysfs attributes, if any. -+ * Helpful for scstadmin to work correctly. -+ */ -+ const char *tgtt_optional_attributes; -+ -+ /* -+ * List of optional, i.e. which could be added by add_target_attribute -+ * command and deleted by del_target_attribute command, sysfs -+ * attributes, if any. Helpful for scstadmin to work correctly. -+ */ -+ const char *tgt_optional_attributes; -+ -+ /** Private, must be inited to 0 by memset() **/ -+ -+ /* List of targets per template, protected by scst_mutex */ -+ struct list_head tgt_list; -+ -+ /* List entry of global templates list */ -+ struct list_head scst_template_list_entry; -+ -+ struct kobject tgtt_kobj; /* kobject for this struct */ -+ -+ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */ -+ int tgtt_active_sysfs_works_count; -+ -+ /* sysfs release completion */ -+ struct completion *tgtt_kobj_release_cmpl; -+ -+ /* -+ * Optional vendor to be reported via the SCSI inquiry data. If NULL, -+ * an SCST device handler specific default value will be used, e.g. -+ * "SCST_FIO" for scst_vdisk file I/O. -+ */ -+ const char *vendor; -+ -+ /* -+ * Optional method that sets the product ID in [buf, buf+size) based -+ * on the device type (byte 0 of the SCSI inquiry data, which contains -+ * the peripheral qualifier in the highest three bits and the -+ * peripheral device type in the lower five bits). -+ */ -+ void (*get_product_id)(const struct scst_tgt_dev *tgt_dev, -+ char *buf, int size); -+ -+ /* -+ * Optional revision to be reported in the SCSI inquiry response. If -+ * NULL, an SCST device handler specific default value will be used, -+ * e.g. " 220" for scst_vdisk file I/O. -+ */ -+ const char *revision; -+ -+ /* -+ * Optional method that writes the serial number of a target device in -+ * [buf, buf+size) and returns the number of bytes written. -+ * -+ * Note: SCST can be configured such that a device can be accessed -+ * from several different transports at the same time. It is important -+ * that all clients see the same USN for proper operation. Overriding -+ * the serial number can lead to subtle misbehavior. Particularly, -+ * "usn" sysfs attribute of the corresponding devices will still show -+ * the devices generated or assigned serial numbers. -+ */ -+ int (*get_serial)(const struct scst_tgt_dev *tgt_dev, char *buf, -+ int size); -+ -+ /* -+ * Optional method that writes the SCSI inquiry vendor-specific data in -+ * [buf, buf+size) and returns the number of bytes written. -+ */ -+ int (*get_vend_specific)(const struct scst_tgt_dev *tgt_dev, char *buf, -+ int size); -+}; -+ -+/* -+ * Threads pool types. Changing them don't forget to change -+ * the corresponding *_STR values in scst_const.h! -+ */ -+enum scst_dev_type_threads_pool_type { -+ /* Each initiator will have dedicated threads pool. */ -+ SCST_THREADS_POOL_PER_INITIATOR = 0, -+ -+ /* All connected initiators will use shared threads pool */ -+ SCST_THREADS_POOL_SHARED, -+ -+ /* Invalid value for scst_parse_threads_pool_type() */ -+ SCST_THREADS_POOL_TYPE_INVALID, -+}; -+ -+/* -+ * SCST dev handler template: defines dev handler's parameters and callback -+ * functions. -+ * -+ * MUST HAVEs define functions that are expected to be defined in order to -+ * work. OPTIONAL says that there is a choice. -+ */ -+struct scst_dev_type { -+ /* SCSI type of the supported device. MUST HAVE */ -+ int type; -+ -+ /* -+ * True, if corresponding function supports execution in -+ * the atomic (non-sleeping) context -+ */ -+ unsigned parse_atomic:1; -+ unsigned alloc_data_buf_atomic:1; -+ unsigned dev_done_atomic:1; -+ -+ /* -+ * Should be true, if exec() is synchronous. This is a hint to SCST core -+ * to optimize commands order management. -+ */ -+ unsigned exec_sync:1; -+ -+ /* -+ * Should be set if the device wants to receive notification of -+ * Persistent Reservation commands (PR OUT only) -+ * Note: The notification will not be send if the command failed -+ */ -+ unsigned pr_cmds_notifications:1; -+ -+ /* -+ * Called to parse CDB from the cmd and initialize -+ * cmd->bufflen and cmd->data_direction (both - REQUIRED). -+ * -+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT, -+ * if the next default state should be used, or -+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic -+ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the -+ * command should not be further processed for now. In the -+ * SCST_CMD_STATE_NEED_THREAD_CTX case the function -+ * will be recalled in the thread context, where sleeping is allowed. -+ * -+ * Pay attention to "atomic" attribute of the cmd, which can be get -+ * by scst_cmd_atomic(): it is true if the function called in the -+ * atomic (non-sleeping) context. -+ * -+ * MUST HAVE -+ */ -+ int (*parse) (struct scst_cmd *cmd); -+ -+ /* -+ * This function allows dev handler to handle data buffer -+ * allocations on its own. -+ * -+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT, -+ * if the next default state should be used, or -+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic -+ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the -+ * command should not be further processed for now. In the -+ * SCST_CMD_STATE_NEED_THREAD_CTX case the function -+ * will be recalled in the thread context, where sleeping is allowed. -+ * -+ * Pay attention to "atomic" attribute of the cmd, which can be get -+ * by scst_cmd_atomic(): it is true if the function called in the -+ * atomic (non-sleeping) context. -+ * -+ * OPTIONAL -+ */ -+ int (*alloc_data_buf) (struct scst_cmd *cmd); -+ -+ /* -+ * Called to execute CDB. Useful, for instance, to implement -+ * data caching. The result of CDB execution is reported via -+ * cmd->scst_cmd_done() callback. -+ * Returns: -+ * - SCST_EXEC_COMPLETED - the cmd is done, go to other ones -+ * - SCST_EXEC_NOT_COMPLETED - the cmd should be sent to SCSI -+ * mid-level. -+ * -+ * If this function provides sync execution, you should set -+ * exec_sync flag and consider to setup dedicated threads by -+ * setting threads_num > 0. -+ * -+ * !! If this function is implemented, scst_check_local_events() !! -+ * !! shall be called inside it just before the actual command's !! -+ * !! execution. !! -+ * -+ * OPTIONAL, if not set, the commands will be sent directly to SCSI -+ * device. -+ */ -+ int (*exec) (struct scst_cmd *cmd); -+ -+ /* -+ * Called to notify dev handler about the result of cmd execution -+ * and perform some post processing. Cmd's fields is_send_status and -+ * resp_data_len should be set by this function, but SCST offers good -+ * defaults. -+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT, -+ * if the next default state should be used, or -+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic -+ * context, but requires sleeping. In the last case, the function -+ * will be recalled in the thread context, where sleeping is allowed. -+ * -+ * Pay attention to "atomic" attribute of the cmd, which can be get -+ * by scst_cmd_atomic(): it is true if the function called in the -+ * atomic (non-sleeping) context. -+ * -+ * OPTIONAL -+ */ -+ int (*dev_done) (struct scst_cmd *cmd); -+ -+ /* -+ * Called to notify dev hander that the command is about to be freed. -+ * -+ * Could be called on IRQ context. -+ * -+ * OPTIONAL -+ */ -+ void (*on_free_cmd) (struct scst_cmd *cmd); -+ -+ /* -+ * Called to execute a task management command. -+ * Returns: -+ * - SCST_MGMT_STATUS_SUCCESS - the command is done with success, -+ * no further actions required -+ * - The SCST_MGMT_STATUS_* error code if the command is failed and -+ * no further actions required -+ * - SCST_DEV_TM_NOT_COMPLETED - regular standard actions for the -+ * command should be done -+ * -+ * Can be called under many internal SCST locks, including under -+ * disabled IRQs, so dev handler should be careful with locking and, -+ * if necessary, pass processing somewhere outside (in a work, e.g.) -+ * -+ * But at the moment it's called under disabled IRQs only for -+ * SCST_ABORT_TASK, however dev handler using it should add a BUG_ON -+ * trap to catch if it's changed in future. -+ * -+ * OPTIONAL -+ */ -+ int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd, -+ struct scst_tgt_dev *tgt_dev); -+ -+ /* -+ * Called to notify dev handler that its sg_tablesize is too low to -+ * satisfy this command's data transfer requirements. Should return -+ * true if exec() callback will split this command's CDB on smaller -+ * transfers, false otherwise. -+ * -+ * Could be called on SIRQ context. -+ * -+ * MUST HAVE, if dev handler supports CDB splitting. -+ */ -+ bool (*on_sg_tablesize_low) (struct scst_cmd *cmd); -+ -+ /* -+ * Called when new device is attaching to the dev handler -+ * Returns 0 on success, error code otherwise. -+ * -+ * OPTIONAL -+ */ -+ int (*attach) (struct scst_device *dev); -+ -+ /* -+ * Called when a device is detaching from the dev handler. -+ * -+ * OPTIONAL -+ */ -+ void (*detach) (struct scst_device *dev); -+ -+ /* -+ * Called when new tgt_dev (session) is attaching to the dev handler. -+ * Returns 0 on success, error code otherwise. -+ * -+ * OPTIONAL -+ */ -+ int (*attach_tgt) (struct scst_tgt_dev *tgt_dev); -+ -+ /* -+ * Called when tgt_dev (session) is detaching from the dev handler. -+ * -+ * OPTIONAL -+ */ -+ void (*detach_tgt) (struct scst_tgt_dev *tgt_dev); -+ -+ /* -+ * This function adds a virtual device. -+ * -+ * If both add_device and del_device callbacks defined, then this -+ * dev handler supposed to support adding/deleting virtual devices. -+ * In this case an "mgmt" entry will be created in the sysfs root for -+ * this handler. The "mgmt" entry will support 2 commands: "add_device" -+ * and "del_device", for which the corresponding callbacks will be called. -+ * Also dev handler can define own commands for the "mgmt" entry, see -+ * mgmt_cmd and mgmt_cmd_help below. -+ * -+ * This approach allows uniform devices management to simplify external -+ * management tools like scstadmin. See README for more details. -+ * -+ * Either both add_device and del_device must be defined, or none. -+ * -+ * MUST HAVE if virtual devices are supported. -+ */ -+ ssize_t (*add_device) (const char *device_name, char *params); -+ -+ /* -+ * This function deletes a virtual device. See comment for add_device -+ * above. -+ * -+ * MUST HAVE if virtual devices are supported. -+ */ -+ ssize_t (*del_device) (const char *device_name); -+ -+ /* -+ * This function called if not "add_device" or "del_device" command is -+ * sent to the mgmt entry (see comment for add_device above). In this -+ * case the command passed to this function as is in a string form. -+ * -+ * OPTIONAL. -+ */ -+ ssize_t (*mgmt_cmd) (char *cmd); -+ -+ /* -+ * Name of the dev handler. Must be unique. MUST HAVE. -+ * -+ * It's SCST_MAX_NAME + few more bytes to match scst_user expectations. -+ */ -+ char name[SCST_MAX_NAME + 10]; -+ -+ /* -+ * Number of threads in this handler's devices' threads pools. -+ * If 0 - no threads will be created, if <0 - creation of the threads -+ * pools is prohibited. Also pay attention to threads_pool_type below. -+ */ -+ int threads_num; -+ -+ /* Threads pool type. Valid only if threads_num > 0. */ -+ enum scst_dev_type_threads_pool_type threads_pool_type; -+ -+ /* Optional default log flags */ -+ const unsigned long default_trace_flags; -+ -+ /* Optional pointer to trace flags */ -+ unsigned long *trace_flags; -+ -+ /* Optional local trace table */ -+ struct scst_trace_log *trace_tbl; -+ -+ /* Optional local trace table help string */ -+ const char *trace_tbl_help; -+ -+ /* Optional help string for mgmt_cmd commands */ -+ const char *mgmt_cmd_help; -+ -+ /* List of parameters for add_device command, if any */ -+ const char *add_device_parameters; -+ -+ /* -+ * List of optional, i.e. which could be added by add_attribute command -+ * and deleted by del_attribute command, sysfs attributes, if any. -+ * Helpful for scstadmin to work correctly. -+ */ -+ const char *devt_optional_attributes; -+ -+ /* -+ * List of optional, i.e. which could be added by add_device_attribute -+ * command and deleted by del_device_attribute command, sysfs -+ * attributes, if any. Helpful for scstadmin to work correctly. -+ */ -+ const char *dev_optional_attributes; -+ -+ /* sysfs attributes, if any */ -+ const struct attribute **devt_attrs; -+ -+ /* sysfs device attributes, if any */ -+ const struct attribute **dev_attrs; -+ -+ /* Pointer to dev handler's private data */ -+ void *devt_priv; -+ -+ /* Pointer to parent dev type in the sysfs hierarchy */ -+ struct scst_dev_type *parent; -+ -+ struct module *module; -+ -+ /** Private, must be inited to 0 by memset() **/ -+ -+ /* list entry in scst_(virtual_)dev_type_list */ -+ struct list_head dev_type_list_entry; -+ -+ struct kobject devt_kobj; /* main handlers/driver */ -+ -+ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */ -+ int devt_active_sysfs_works_count; -+ -+ /* To wait until devt_kobj released */ -+ struct completion *devt_kobj_release_compl; -+}; -+ -+/* -+ * An SCST target, analog of SCSI target port. -+ */ -+struct scst_tgt { -+ /* List of remote sessions per target, protected by scst_mutex */ -+ struct list_head sess_list; -+ -+ /* List entry of targets per template (tgts_list) */ -+ struct list_head tgt_list_entry; -+ -+ struct scst_tgt_template *tgtt; /* corresponding target template */ -+ -+ struct scst_acg *default_acg; /* default acg for this target */ -+ -+ struct list_head tgt_acg_list; /* target ACG groups */ -+ -+ /* -+ * Maximum SG table size. Needed here, since different cards on the -+ * same target template can have different SG table limitations. -+ */ -+ int sg_tablesize; -+ -+ /* Used for storage of target driver private stuff */ -+ void *tgt_priv; -+ -+ /* -+ * The following fields used to store and retry cmds if target's -+ * internal queue is full, so the target is unable to accept -+ * the cmd returning QUEUE FULL. -+ * They protected by tgt_lock, where necessary. -+ */ -+ bool retry_timer_active; -+ struct timer_list retry_timer; -+ atomic_t finished_cmds; -+ int retry_cmds; -+ spinlock_t tgt_lock; -+ struct list_head retry_cmd_list; -+ -+ /* Used to wait until session finished to unregister */ -+ wait_queue_head_t unreg_waitQ; -+ -+ /* Name of the target */ -+ char *tgt_name; -+ -+ /* User comment to it to let easier distinguish targets */ -+ char *tgt_comment; -+ -+ uint16_t rel_tgt_id; -+ -+ /* sysfs release completion */ -+ struct completion *tgt_kobj_release_cmpl; -+ -+ struct kobject tgt_kobj; /* main targets/target kobject */ -+ struct kobject *tgt_sess_kobj; /* target/sessions/ */ -+ struct kobject *tgt_luns_kobj; /* target/luns/ */ -+ struct kobject *tgt_ini_grp_kobj; /* target/ini_groups/ */ -+}; -+ -+#ifdef CONFIG_SCST_MEASURE_LATENCY -+ -+/* Defines extended latency statistics */ -+struct scst_ext_latency_stat { -+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd; -+ unsigned int processed_cmds_rd; -+ uint64_t min_scst_time_rd, min_tgt_time_rd, min_dev_time_rd; -+ uint64_t max_scst_time_rd, max_tgt_time_rd, max_dev_time_rd; -+ -+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr; -+ unsigned int processed_cmds_wr; -+ uint64_t min_scst_time_wr, min_tgt_time_wr, min_dev_time_wr; -+ uint64_t max_scst_time_wr, max_tgt_time_wr, max_dev_time_wr; -+}; -+ -+#define SCST_IO_SIZE_THRESHOLD_SMALL (8*1024) -+#define SCST_IO_SIZE_THRESHOLD_MEDIUM (32*1024) -+#define SCST_IO_SIZE_THRESHOLD_LARGE (128*1024) -+#define SCST_IO_SIZE_THRESHOLD_VERY_LARGE (512*1024) -+ -+#define SCST_LATENCY_STAT_INDEX_SMALL 0 -+#define SCST_LATENCY_STAT_INDEX_MEDIUM 1 -+#define SCST_LATENCY_STAT_INDEX_LARGE 2 -+#define SCST_LATENCY_STAT_INDEX_VERY_LARGE 3 -+#define SCST_LATENCY_STAT_INDEX_OTHER 4 -+#define SCST_LATENCY_STATS_NUM (SCST_LATENCY_STAT_INDEX_OTHER + 1) -+ -+#endif /* CONFIG_SCST_MEASURE_LATENCY */ -+ -+struct scst_io_stat_entry { -+ uint64_t cmd_count; -+ uint64_t io_byte_count; -+}; -+ -+/* -+ * SCST session, analog of SCSI I_T nexus -+ */ -+struct scst_session { -+ /* -+ * Initialization phase, one of SCST_SESS_IPH_* constants, protected by -+ * sess_list_lock -+ */ -+ int init_phase; -+ -+ struct scst_tgt *tgt; /* corresponding target */ -+ -+ /* Used for storage of target driver private stuff */ -+ void *tgt_priv; -+ -+ /* session's async flags */ -+ unsigned long sess_aflags; -+ -+ /* -+ * Hash list for tgt_dev's for this session with size and fn. It isn't -+ * hlist_entry, because we need ability to go over the list in the -+ * reverse order. Protected by scst_mutex and suspended activity. -+ */ -+#define SESS_TGT_DEV_LIST_HASH_SIZE (1 << 5) -+#define SESS_TGT_DEV_LIST_HASH_FN(val) ((val) & (SESS_TGT_DEV_LIST_HASH_SIZE - 1)) -+ struct list_head sess_tgt_dev_list[SESS_TGT_DEV_LIST_HASH_SIZE]; -+ -+ /* -+ * List of cmds in this session. Protected by sess_list_lock. -+ * -+ * We must always keep commands in the sess list from the -+ * very beginning, because otherwise they can be missed during -+ * TM processing. -+ */ -+ struct list_head sess_cmd_list; -+ -+ spinlock_t sess_list_lock; /* protects sess_cmd_list, etc */ -+ -+ atomic_t refcnt; /* get/put counter */ -+ -+ /* -+ * Alive commands for this session. ToDo: make it part of the common -+ * IO flow control. -+ */ -+ atomic_t sess_cmd_count; -+ -+ /* Some statistics. Protected by sess_list_lock. */ -+ struct scst_io_stat_entry io_stats[SCST_DATA_DIR_MAX]; -+ -+ /* Access control for this session and list entry there */ -+ struct scst_acg *acg; -+ -+ /* Initiator port transport id */ -+ uint8_t *transport_id; -+ -+ /* List entry for the sessions list inside ACG */ -+ struct list_head acg_sess_list_entry; -+ -+ struct delayed_work hw_pending_work; -+ -+ /* Name of attached initiator */ -+ const char *initiator_name; -+ -+ /* List entry of sessions per target */ -+ struct list_head sess_list_entry; -+ -+ /* List entry for the list that keeps session, waiting for the init */ -+ struct list_head sess_init_list_entry; -+ -+ /* -+ * List entry for the list that keeps session, waiting for the shutdown -+ */ -+ struct list_head sess_shut_list_entry; -+ -+ /* -+ * Lists of deferred during session initialization commands. -+ * Protected by sess_list_lock. -+ */ -+ struct list_head init_deferred_cmd_list; -+ struct list_head init_deferred_mcmd_list; -+ -+ /* -+ * Shutdown phase, one of SCST_SESS_SPH_* constants, unprotected. -+ * Async. relating to init_phase, must be a separate variable, because -+ * session could be unregistered before async. registration is finished. -+ */ -+ unsigned long shut_phase; -+ -+ /* Used if scst_unregister_session() called in wait mode */ -+ struct completion *shutdown_compl; -+ -+ /* sysfs release completion */ -+ struct completion *sess_kobj_release_cmpl; -+ -+ unsigned int sess_kobj_ready:1; -+ -+ struct kobject sess_kobj; /* kobject for this struct */ -+ -+ /* -+ * Functions and data for user callbacks from scst_register_session() -+ * and scst_unregister_session() -+ */ -+ void *reg_sess_data; -+ void (*init_result_fn) (struct scst_session *sess, void *data, -+ int result); -+ void (*unreg_done_fn) (struct scst_session *sess); -+ -+#ifdef CONFIG_SCST_MEASURE_LATENCY -+ /* -+ * Must be the last to allow to work with drivers who don't know -+ * about this config time option. -+ */ -+ spinlock_t lat_lock; -+ uint64_t scst_time, tgt_time, dev_time; -+ unsigned int processed_cmds; -+ uint64_t min_scst_time, min_tgt_time, min_dev_time; -+ uint64_t max_scst_time, max_tgt_time, max_dev_time; -+ struct scst_ext_latency_stat sess_latency_stat[SCST_LATENCY_STATS_NUM]; -+#endif -+}; -+ -+/* -+ * SCST_PR_ABORT_ALL TM function helper structure -+ */ -+struct scst_pr_abort_all_pending_mgmt_cmds_counter { -+ /* -+ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM -+ * commands. -+ */ -+ atomic_t pr_abort_pending_cnt; -+ -+ /* Saved completion routine */ -+ void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state, -+ enum scst_exec_context pref_context); -+ -+ /* -+ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM -+ * commands, which not yet aborted all affected commands and -+ * a completion to signal, when it's done. -+ */ -+ atomic_t pr_aborting_cnt; -+ struct completion pr_aborting_cmpl; -+}; -+ -+/* -+ * Structure to control commands' queuing and threads pool processing the queue -+ */ -+struct scst_cmd_threads { -+ spinlock_t cmd_list_lock; -+ struct list_head active_cmd_list; /* commands queue */ -+ wait_queue_head_t cmd_list_waitQ; -+ -+ struct io_context *io_context; /* IO context of the threads pool */ -+ int io_context_refcnt; -+ -+ bool io_context_ready; -+ -+ /* io_context_mutex protects io_context and io_context_refcnt. */ -+ struct mutex io_context_mutex; -+ -+ int nr_threads; /* number of processing threads */ -+ struct list_head threads_list; /* processing threads */ -+ -+ struct list_head lists_list_entry; -+}; -+ -+/* -+ * Used to execute cmd's in order of arrival, honoring SCSI task attributes -+ */ -+struct scst_order_data { -+ /* -+ * Protected by sn_lock, except expected_sn, which is protected by -+ * itself. Curr_sn must have the same size as expected_sn to -+ * overflow simultaneously. -+ */ -+ int def_cmd_count; -+ spinlock_t sn_lock; -+ unsigned int expected_sn; -+ unsigned int curr_sn; -+ int hq_cmd_count; -+ struct list_head deferred_cmd_list; -+ struct list_head skipped_sn_list; -+ -+ /* -+ * Set if the prev cmd was ORDERED. Size and, hence, alignment must -+ * allow unprotected modifications independently to the neighbour fields. -+ */ -+ unsigned long prev_cmd_ordered; -+ -+ int num_free_sn_slots; /* if it's <0, then all slots are busy */ -+ atomic_t *cur_sn_slot; -+ atomic_t sn_slots[15]; -+}; -+ -+/* -+ * SCST command, analog of I_T_L_Q nexus or task -+ */ -+struct scst_cmd { -+ /* List entry for below *_cmd_threads */ -+ struct list_head cmd_list_entry; -+ -+ /* Pointer to lists of commands with the lock */ -+ struct scst_cmd_threads *cmd_threads; -+ -+ atomic_t cmd_ref; -+ -+ struct scst_session *sess; /* corresponding session */ -+ -+ atomic_t *cpu_cmd_counter; -+ -+ /* Cmd state, one of SCST_CMD_STATE_* constants */ -+ int state; -+ -+ /************************************************************* -+ ** Cmd's flags -+ *************************************************************/ -+ -+ /* -+ * Set if expected_sn should be incremented, i.e. cmd was sent -+ * for execution -+ */ -+ unsigned int sent_for_exec:1; -+ -+ /* Set if the cmd's action is completed */ -+ unsigned int completed:1; -+ -+ /* Set if we should ignore Unit Attention in scst_check_sense() */ -+ unsigned int ua_ignore:1; -+ -+ /* Set if cmd is being processed in atomic context */ -+ unsigned int atomic:1; -+ -+ /* Set if this command was sent in double UA possible state */ -+ unsigned int double_ua_possible:1; -+ -+ /* Set if this command contains status */ -+ unsigned int is_send_status:1; -+ -+ /* Set if cmd is being retried */ -+ unsigned int retry:1; -+ -+ /* Set if cmd is internally generated */ -+ unsigned int internal:1; -+ -+ /* Set if the device was blocked by scst_check_blocked_dev() */ -+ unsigned int unblock_dev:1; -+ -+ /* Set if this cmd incremented dev->pr_readers_count */ -+ unsigned int dec_pr_readers_count_needed:1; -+ -+ /* Set if scst_dec_on_dev_cmd() call is needed on the cmd's finish */ -+ unsigned int dec_on_dev_needed:1; -+ -+ /* Set if cmd is queued as hw pending */ -+ unsigned int cmd_hw_pending:1; -+ -+ /* -+ * Set, if for this cmd required to not have any IO or FS calls on -+ * memory buffers allocations, at least for READ and WRITE commands. -+ * Needed for cases like file systems mounted over scst_local's -+ * devices. -+ */ -+ unsigned noio_mem_alloc:1; -+ -+ /* -+ * Set if the target driver wants to alloc data buffers on its own. -+ * In this case alloc_data_buf() must be provided in the target driver -+ * template. -+ */ -+ unsigned int tgt_need_alloc_data_buf:1; -+ -+ /* -+ * Set by SCST if the custom data buffer allocation by the target driver -+ * succeeded. -+ */ -+ unsigned int tgt_data_buf_alloced:1; -+ -+ /* Set if custom data buffer allocated by dev handler */ -+ unsigned int dh_data_buf_alloced:1; -+ -+ /* Set if the target driver called scst_set_expected() */ -+ unsigned int expected_values_set:1; -+ -+ /* -+ * Set if the SG buffer was modified by scst_adjust_sg() -+ */ -+ unsigned int sg_buff_modified:1; -+ -+ /* -+ * Set if cmd buffer was vmallocated and copied from more -+ * then one sg chunk -+ */ -+ unsigned int sg_buff_vmallocated:1; -+ -+ /* -+ * Set if scst_cmd_init_stage1_done() called and the target -+ * want that preprocessing_done() will be called -+ */ -+ unsigned int preprocessing_only:1; -+ -+ /* Set if cmd's SN was set */ -+ unsigned int sn_set:1; -+ -+ /* Set if hq_cmd_count was incremented */ -+ unsigned int hq_cmd_inced:1; -+ -+ /* -+ * Set if scst_cmd_init_stage1_done() called and the target wants -+ * that the SN for the cmd won't be assigned until scst_restart_cmd() -+ */ -+ unsigned int set_sn_on_restart_cmd:1; -+ -+ /* Set if the cmd's must not use sgv cache for data buffer */ -+ unsigned int no_sgv:1; -+ -+ /* -+ * Set if target driver may need to call dma_sync_sg() or similar -+ * function before transferring cmd' data to the target device -+ * via DMA. -+ */ -+ unsigned int may_need_dma_sync:1; -+ -+ /* Set if the cmd was done or aborted out of its SN */ -+ unsigned int out_of_sn:1; -+ -+ /* Set if increment expected_sn in cmd->scst_cmd_done() */ -+ unsigned int inc_expected_sn_on_done:1; -+ -+ /* Set if tgt_sn field is valid */ -+ unsigned int tgt_sn_set:1; -+ -+ /* Set if any direction residual is possible */ -+ unsigned int resid_possible:1; -+ -+ /* Set if cmd is done */ -+ unsigned int done:1; -+ -+ /* -+ * Set if cmd is finished. Used under sess_list_lock to sync -+ * between scst_finish_cmd() and scst_abort_cmd() -+ */ -+ unsigned int finished:1; -+ -+ /* -+ * Set if scst_check_local_events() can be called more than once. Set by -+ * scst_pre_check_local_events(). -+ */ -+ unsigned int check_local_events_once_done:1; -+ -+#ifdef CONFIG_SCST_DEBUG_TM -+ /* Set if the cmd was delayed by task management debugging code */ -+ unsigned int tm_dbg_delayed:1; -+ -+ /* Set if the cmd must be ignored by task management debugging code */ -+ unsigned int tm_dbg_immut:1; -+#endif -+ -+ /**************************************************************/ -+ -+ /* cmd's async flags */ -+ unsigned long cmd_flags; -+ -+ /* Keeps status of cmd's status/data delivery to remote initiator */ -+ int delivery_status; -+ -+ struct scst_tgt_template *tgtt; /* to save extra dereferences */ -+ struct scst_tgt *tgt; /* to save extra dereferences */ -+ struct scst_device *dev; /* to save extra dereferences */ -+ -+ /* corresponding I_T_L device for this cmd */ -+ struct scst_tgt_dev *tgt_dev; -+ -+ struct scst_order_data *cur_order_data; /* to save extra dereferences */ -+ -+ uint64_t lun; /* LUN for this cmd */ -+ -+ unsigned long start_time; -+ -+ /* List entry for tgt_dev's SN related lists */ -+ struct list_head sn_cmd_list_entry; -+ -+ /* Cmd's serial number, used to execute cmd's in order of arrival */ -+ unsigned int sn; -+ -+ /* The corresponding sn_slot in tgt_dev->sn_slots */ -+ atomic_t *sn_slot; -+ -+ /* List entry for sess's sess_cmd_list */ -+ struct list_head sess_cmd_list_entry; -+ -+ /* -+ * Used to found the cmd by scst_find_cmd_by_tag(). Set by the -+ * target driver on the cmd's initialization time -+ */ -+ uint64_t tag; -+ -+ uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */ -+ -+ uint8_t *cdb; /* Pointer on CDB. Points on cdb_buf for small CDBs. */ -+ unsigned short cdb_len; -+ uint8_t cdb_buf[SCST_MAX_CDB_SIZE]; -+ -+ enum scst_cdb_flags op_flags; -+ const char *op_name; -+ -+ enum scst_cmd_queue_type queue_type; -+ -+ int timeout; /* CDB execution timeout in seconds */ -+ int retries; /* Amount of retries that will be done by SCSI mid-level */ -+ -+ /* SCSI data direction, one of SCST_DATA_* constants */ -+ scst_data_direction data_direction; -+ -+ /* Remote initiator supplied values, if any */ -+ scst_data_direction expected_data_direction; -+ int expected_transfer_len; -+ int expected_out_transfer_len; /* for bidi writes */ -+ -+ /* -+ * Cmd data length. Could be different from bufflen for commands like -+ * VERIFY, which transfer different amount of data (if any), than -+ * processed. -+ */ -+ int data_len; -+ -+ /* Completion routine */ -+ void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state, -+ enum scst_exec_context pref_context); -+ -+ struct sgv_pool_obj *sgv; /* sgv object */ -+ int bufflen; /* cmd buffer length */ -+ struct scatterlist *sg; /* cmd data buffer SG vector */ -+ int sg_cnt; /* SG segments count */ -+ -+ /* -+ * Response data length in data buffer. Must not be set -+ * directly, use scst_set_resp_data_len() for that. -+ */ -+ int resp_data_len; -+ -+ /* -+ * Response data length adjusted on residual, i.e. -+ * min(expected_len, resp_len), if expected len set. -+ */ -+ int adjusted_resp_data_len; -+ -+ /* -+ * Data length to write, i.e. transfer from the initiator. Might be -+ * different from (out_)bufflen, if the initiator asked too big or too -+ * small expected(_out_)transfer_len. -+ */ -+ int write_len; -+ -+ /* -+ * Write sg and sg_cnt to point out either on sg/sg_cnt, or on -+ * out_sg/out_sg_cnt. -+ */ -+ struct scatterlist **write_sg; -+ int *write_sg_cnt; -+ -+ /* scst_get_sg_buf_[first,next]() support */ -+ struct scatterlist *get_sg_buf_cur_sg_entry; -+ int get_sg_buf_entry_num; -+ -+ /* Bidirectional transfers support */ -+ int out_bufflen; /* WRITE buffer length */ -+ struct sgv_pool_obj *out_sgv; /* WRITE sgv object */ -+ struct scatterlist *out_sg; /* WRITE data buffer SG vector */ -+ int out_sg_cnt; /* WRITE SG segments count */ -+ -+ /* -+ * Used if both target driver and dev handler request own memory -+ * allocation. In other cases, both are equal to sg and sg_cnt -+ * correspondingly. -+ * -+ * If target driver requests own memory allocations, it MUST use -+ * functions scst_cmd_get_tgt_sg*() to get sg and sg_cnt! Otherwise, -+ * it may use functions scst_cmd_get_sg*(). -+ */ -+ struct scatterlist *tgt_sg; -+ int tgt_sg_cnt; -+ struct scatterlist *tgt_out_sg; /* bidirectional */ -+ int tgt_out_sg_cnt; /* bidirectional */ -+ -+ /* -+ * The status fields in case of errors must be set using -+ * scst_set_cmd_error_status()! -+ */ -+ uint8_t status; /* status byte from target device */ -+ uint8_t msg_status; /* return status from host adapter itself */ -+ uint8_t host_status; /* set by low-level driver to indicate status */ -+ uint8_t driver_status; /* set by mid-level */ -+ -+ uint8_t *sense; /* pointer to sense buffer */ -+ unsigned short sense_valid_len; /* length of valid sense data */ -+ unsigned short sense_buflen; /* length of the sense buffer, if any */ -+ -+ /* Start time when cmd was sent to rdy_to_xfer() or xmit_response() */ -+ unsigned long hw_pending_start; -+ -+ /* Used for storage of target driver private stuff */ -+ void *tgt_priv; -+ -+ /* Used for storage of dev handler private stuff */ -+ void *dh_priv; -+ -+ /* Used to restore sg if it was modified by scst_adjust_sg() */ -+ struct scatterlist *orig_sg; -+ int *p_orig_sg_cnt; -+ int orig_sg_cnt, orig_sg_entry, orig_entry_len; -+ -+ /* Used to retry commands in case of double UA */ -+ int dbl_ua_orig_resp_data_len, dbl_ua_orig_data_direction; -+ -+ /* -+ * List of the corresponding mgmt cmds, if any. Protected by -+ * sess_list_lock. -+ */ -+ struct list_head mgmt_cmd_list; -+ -+ /* List entry for dev's blocked_cmd_list */ -+ struct list_head blocked_cmd_list_entry; -+ -+ /* Counter of the corresponding SCST_PR_ABORT_ALL TM commands */ -+ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_abort_counter; -+ -+ struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */ -+ -+#ifdef CONFIG_SCST_MEASURE_LATENCY -+ /* -+ * Must be the last to allow to work with drivers who don't know -+ * about this config time option. -+ */ -+ uint64_t start, curr_start, parse_time, alloc_buf_time; -+ uint64_t restart_waiting_time, rdy_to_xfer_time; -+ uint64_t pre_exec_time, exec_time, dev_done_time; -+ uint64_t xmit_time, tgt_on_free_time, dev_on_free_time; -+#endif -+}; -+ -+/* -+ * Parameters for SCST management commands -+ */ -+struct scst_rx_mgmt_params { -+ int fn; -+ uint64_t tag; -+ const uint8_t *lun; -+ int lun_len; -+ uint32_t cmd_sn; -+ int atomic; -+ void *tgt_priv; -+ unsigned char tag_set; -+ unsigned char lun_set; -+ unsigned char cmd_sn_set; -+}; -+ -+/* -+ * A stub structure to link an management command and affected regular commands -+ */ -+struct scst_mgmt_cmd_stub { -+ struct scst_mgmt_cmd *mcmd; -+ -+ /* List entry in cmd->mgmt_cmd_list */ -+ struct list_head cmd_mgmt_cmd_list_entry; -+ -+ /* Set if the cmd was counted in mcmd->cmd_done_wait_count */ -+ unsigned int done_counted:1; -+ -+ /* Set if the cmd was counted in mcmd->cmd_finish_wait_count */ -+ unsigned int finish_counted:1; -+}; -+ -+/* -+ * SCST task management structure -+ */ -+struct scst_mgmt_cmd { -+ /* List entry for *_mgmt_cmd_list */ -+ struct list_head mgmt_cmd_list_entry; -+ -+ struct scst_session *sess; -+ -+ atomic_t *cpu_cmd_counter; -+ -+ /* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */ -+ int state; -+ -+ int fn; /* task management function */ -+ -+ /* Set if device(s) should be unblocked after mcmd's finish */ -+ unsigned int needs_unblocking:1; -+ unsigned int lun_set:1; /* set, if lun field is valid */ -+ unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */ -+ -+ /* -+ * Number of commands to finish before sending response, -+ * protected by scst_mcmd_lock -+ */ -+ int cmd_finish_wait_count; -+ -+ /* -+ * Number of commands to complete (done) before resetting reservation, -+ * protected by scst_mcmd_lock -+ */ -+ int cmd_done_wait_count; -+ -+ /* Number of completed commands, protected by scst_mcmd_lock */ -+ int completed_cmd_count; -+ -+ uint64_t lun; /* LUN for this mgmt cmd */ -+ /* or (and for iSCSI) */ -+ uint64_t tag; /* tag of the corresponding cmd */ -+ -+ uint32_t cmd_sn; /* affected command's highest SN */ -+ -+ /* corresponding cmd (to be aborted, found by tag) */ -+ struct scst_cmd *cmd_to_abort; -+ -+ /* corresponding device for this mgmt cmd (found by lun) */ -+ struct scst_tgt_dev *mcmd_tgt_dev; -+ -+ /* completion status, one of the SCST_MGMT_STATUS_* constants */ -+ int status; -+ -+ /* Used for storage of target driver private stuff or origin PR cmd */ -+ union { -+ void *tgt_priv; -+ struct scst_cmd *origin_pr_cmd; -+ }; -+}; -+ -+/* -+ * Persistent reservations registrant -+ */ -+struct scst_dev_registrant { -+ uint8_t *transport_id; -+ uint16_t rel_tgt_id; -+ __be64 key; -+ -+ /* tgt_dev (I_T nexus) for this registrant, if any */ -+ struct scst_tgt_dev *tgt_dev; -+ -+ /* List entry for dev_registrants_list */ -+ struct list_head dev_registrants_list_entry; -+ -+ /* 2 auxiliary fields used to rollback changes for errors, etc. */ -+ struct list_head aux_list_entry; -+ __be64 rollback_key; -+}; -+ -+/* -+ * SCST device -+ */ -+struct scst_device { -+ unsigned short type; /* SCSI type of the device */ -+ -+ /************************************************************* -+ ** Dev's flags. Updates serialized by dev_lock or suspended -+ ** activity -+ *************************************************************/ -+ -+ /* Set if dev is RESERVED */ -+ unsigned short dev_reserved:1; -+ -+ /* Set if double reset UA is possible */ -+ unsigned short dev_double_ua_possible:1; -+ -+ /* If set, dev is read only */ -+ unsigned short rd_only:1; -+ -+ /* Set, if a strictly serialized cmd is waiting blocked */ -+ unsigned short strictly_serialized_cmd_waiting:1; -+ -+ /* -+ * Set, if this device is being unregistered. Useful to let sysfs -+ * attributes know when they should exit immediatelly to prevent -+ * possible deadlocks with their device unregistration waiting for -+ * their kobj last put. -+ */ -+ unsigned short dev_unregistering:1; -+ -+ /**************************************************************/ -+ -+ /************************************************************* -+ ** Dev's control mode page related values. Updates serialized -+ ** by scst_block_dev(). Modified independently to the above and -+ ** below fields, hence the alignment. -+ *************************************************************/ -+ -+ unsigned int queue_alg:4 __attribute__((aligned(sizeof(long)))); -+ unsigned int tst:3; -+ unsigned int tas:1; -+ unsigned int swp:1; -+ unsigned int d_sense:1; -+ -+ /* -+ * Set if device implements own ordered commands management. If not set -+ * and queue_alg is SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER, -+ * expected_sn will be incremented only after commands finished. -+ */ -+ unsigned int has_own_order_mgmt:1; -+ -+ /**************************************************************/ -+ -+ /* How many cmds alive on this dev */ -+ atomic_t dev_cmd_count; -+ -+ spinlock_t dev_lock; /* device lock */ -+ -+ /* -+ * How many times device was blocked for new cmds execution. -+ * Protected by dev_lock. -+ */ -+ int block_count; -+ -+ /* -+ * How many there are "on_dev" commands, i.e. ones who passed -+ * scst_check_blocked_dev(). Protected by dev_lock. -+ */ -+ int on_dev_cmd_count; -+ -+ /* -+ * How many threads are checking commands for PR allowance. -+ * Protected by dev_lock. -+ */ -+ int pr_readers_count; -+ -+ /* -+ * Set if dev is persistently reserved. Protected by dev_pr_mutex. -+ * Modified independently to the above field, hence the alignment. -+ */ -+ unsigned int pr_is_set:1 __attribute__((aligned(sizeof(long)))); -+ -+ /* -+ * Set if there is a thread changing or going to change PR state(s). -+ * Protected by dev_pr_mutex. -+ */ -+ unsigned int pr_writer_active:1; -+ -+ struct scst_dev_type *handler; /* corresponding dev handler */ -+ -+ /* Used for storage of dev handler private stuff */ -+ void *dh_priv; -+ -+ /* Corresponding real SCSI device, could be NULL for virtual devices */ -+ struct scsi_device *scsi_dev; -+ -+ /* List of commands with lock, if dedicated threads are used */ -+ struct scst_cmd_threads dev_cmd_threads; -+ -+ /* Memory limits for this device */ -+ struct scst_mem_lim dev_mem_lim; -+ -+ /************************************************************* -+ ** Persistent reservation fields. Protected by dev_pr_mutex. -+ *************************************************************/ -+ -+ /* -+ * True if persist through power loss is activated. Modified -+ * independently to the above field, hence the alignment. -+ */ -+ unsigned short pr_aptpl:1 __attribute__((aligned(sizeof(long)))); -+ -+ /* Persistent reservation type */ -+ uint8_t pr_type; -+ -+ /* Persistent reservation scope */ -+ uint8_t pr_scope; -+ -+ /* Mutex to protect PR operations */ -+ struct mutex dev_pr_mutex; -+ -+ /* Persistent reservation generation value */ -+ uint32_t pr_generation; -+ -+ /* Reference to registrant - persistent reservation holder */ -+ struct scst_dev_registrant *pr_holder; -+ -+ /* List of dev's registrants */ -+ struct list_head dev_registrants_list; -+ -+ /* -+ * Count of connected tgt_devs from transports, which don't support -+ * PRs, i.e. don't have get_initiator_port_transport_id(). Protected -+ * by scst_mutex. -+ */ -+ int not_pr_supporting_tgt_devs_num; -+ -+ struct scst_order_data dev_order_data; -+ -+ /* Persist through power loss files */ -+ char *pr_file_name; -+ char *pr_file_name1; -+ -+ /**************************************************************/ -+ -+ /* List of blocked commands, protected by dev_lock. */ -+ struct list_head blocked_cmd_list; -+ -+ /* A list entry used during TM, protected by scst_mutex */ -+ struct list_head tm_dev_list_entry; -+ -+ int virt_id; /* virtual device internal ID */ -+ -+ /* Pointer to virtual device name, for convenience only */ -+ char *virt_name; -+ -+ struct list_head dev_list_entry; /* list entry in global devices list */ -+ -+ /* -+ * List of tgt_dev's, one per session, protected by scst_mutex or -+ * dev_lock for reads and both for writes -+ */ -+ struct list_head dev_tgt_dev_list; -+ -+ /* List of acg_dev's, one per acg, protected by scst_mutex */ -+ struct list_head dev_acg_dev_list; -+ -+ /* Number of threads in the device's threads pools */ -+ int threads_num; -+ -+ /* Threads pool type of the device. Valid only if threads_num > 0. */ -+ enum scst_dev_type_threads_pool_type threads_pool_type; -+ -+ /* sysfs release completion */ -+ struct completion *dev_kobj_release_cmpl; -+ -+ struct kobject dev_kobj; /* kobject for this struct */ -+ struct kobject *dev_exp_kobj; /* exported groups */ -+ -+ /* Export number in the dev's sysfs list. Protected by scst_mutex */ -+ int dev_exported_lun_num; -+}; -+ -+/* -+ * Used to store threads local tgt_dev specific data -+ */ -+struct scst_thr_data_hdr { -+ /* List entry in tgt_dev->thr_data_list */ -+ struct list_head thr_data_list_entry; -+ struct task_struct *owner_thr; /* the owner thread */ -+ atomic_t ref; -+ /* Function that will be called on the tgt_dev destruction */ -+ void (*free_fn) (struct scst_thr_data_hdr *data); -+}; -+ -+/* -+ * Used to clearly dispose async io_context -+ */ -+struct scst_async_io_context_keeper { -+ struct kref aic_keeper_kref; -+ bool aic_ready; -+ struct io_context *aic; -+ struct task_struct *aic_keeper_thr; -+ wait_queue_head_t aic_keeper_waitQ; -+}; -+ -+/* -+ * Used to store per-session specific device information, analog of -+ * SCSI I_T_L nexus. -+ */ -+struct scst_tgt_dev { -+ /* List entry in sess->sess_tgt_dev_list */ -+ struct list_head sess_tgt_dev_list_entry; -+ -+ struct scst_device *dev; /* to save extra dereferences */ -+ uint64_t lun; /* to save extra dereferences */ -+ -+ gfp_t gfp_mask; -+ struct sgv_pool *pool; -+ int max_sg_cnt; -+ -+ /* -+ * Tgt_dev's async flags. Modified independently to the neighbour -+ * fields. -+ */ -+ unsigned long tgt_dev_flags; -+ -+ /* Used for storage of dev handler private stuff */ -+ void *dh_priv; -+ -+ /* How many cmds alive on this dev in this session */ -+ atomic_t tgt_dev_cmd_count; -+ -+ struct scst_order_data *curr_order_data; -+ struct scst_order_data tgt_dev_order_data; -+ -+ /* List of scst_thr_data_hdr and lock */ -+ spinlock_t thr_data_lock; -+ struct list_head thr_data_list; -+ -+ /* Pointer to lists of commands with the lock */ -+ struct scst_cmd_threads *active_cmd_threads; -+ -+ /* Union to save some CPU cache footprint */ -+ union { -+ struct { -+ /* Copy to save fast path dereference */ -+ struct io_context *async_io_context; -+ -+ struct scst_async_io_context_keeper *aic_keeper; -+ }; -+ -+ /* Lists of commands with lock, if dedicated threads are used */ -+ struct scst_cmd_threads tgt_dev_cmd_threads; -+ }; -+ -+ spinlock_t tgt_dev_lock; /* per-session device lock */ -+ -+ /* List of UA's for this device, protected by tgt_dev_lock */ -+ struct list_head UA_list; -+ -+ struct scst_session *sess; /* corresponding session */ -+ struct scst_acg_dev *acg_dev; /* corresponding acg_dev */ -+ -+ /* Reference to registrant to find quicker */ -+ struct scst_dev_registrant *registrant; -+ -+ /* List entry in dev->dev_tgt_dev_list */ -+ struct list_head dev_tgt_dev_list_entry; -+ -+ /* Internal tmp list entry */ -+ struct list_head extra_tgt_dev_list_entry; -+ -+ /* Set if INQUIRY DATA HAS CHANGED UA is needed */ -+ unsigned int inq_changed_ua_needed:1; -+ -+ /* -+ * Stored Unit Attention sense and its length for possible -+ * subsequent REQUEST SENSE. Both protected by tgt_dev_lock. -+ */ -+ unsigned short tgt_dev_valid_sense_len; -+ uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE]; -+ -+ /* sysfs release completion */ -+ struct completion *tgt_dev_kobj_release_cmpl; -+ -+ struct kobject tgt_dev_kobj; /* kobject for this struct */ -+ -+#ifdef CONFIG_SCST_MEASURE_LATENCY -+ /* -+ * Must be the last to allow to work with drivers who don't know -+ * about this config time option. -+ * -+ * Protected by sess->lat_lock. -+ */ -+ uint64_t scst_time, tgt_time, dev_time; -+ unsigned int processed_cmds; -+ struct scst_ext_latency_stat dev_latency_stat[SCST_LATENCY_STATS_NUM]; -+#endif -+}; -+ -+/* -+ * Used to store ACG-specific device information, like LUN -+ */ -+struct scst_acg_dev { -+ struct scst_device *dev; /* corresponding device */ -+ -+ uint64_t lun; /* device's LUN in this acg */ -+ -+ /* If set, the corresponding LU is read only */ -+ unsigned int rd_only:1; -+ -+ struct scst_acg *acg; /* parent acg */ -+ -+ /* List entry in dev->dev_acg_dev_list */ -+ struct list_head dev_acg_dev_list_entry; -+ -+ /* List entry in acg->acg_dev_list */ -+ struct list_head acg_dev_list_entry; -+ -+ /* kobject for this structure */ -+ struct kobject acg_dev_kobj; -+ -+ /* sysfs release completion */ -+ struct completion *acg_dev_kobj_release_cmpl; -+ -+ /* Name of the link to the corresponding LUN */ -+ char acg_dev_link_name[20]; -+}; -+ -+/* -+ * ACG - access control group. Used to store group related -+ * control information. -+ */ -+struct scst_acg { -+ /* Owner target */ -+ struct scst_tgt *tgt; -+ -+ /* List of acg_dev's in this acg, protected by scst_mutex */ -+ struct list_head acg_dev_list; -+ -+ /* List of attached sessions, protected by scst_mutex */ -+ struct list_head acg_sess_list; -+ -+ /* List of attached acn's, protected by scst_mutex */ -+ struct list_head acn_list; -+ -+ /* List entry in acg_lists */ -+ struct list_head acg_list_entry; -+ -+ /* Name of this acg */ -+ const char *acg_name; -+ -+ /* Type of I/O initiators grouping */ -+ int acg_io_grouping_type; -+ -+ /* CPU affinity for threads in this ACG */ -+ cpumask_t acg_cpu_mask; -+ -+ unsigned int tgt_acg:1; -+ -+ /* sysfs release completion */ -+ struct completion *acg_kobj_release_cmpl; -+ -+ /* kobject for this structure */ -+ struct kobject acg_kobj; -+ -+ struct kobject *luns_kobj; -+ struct kobject *initiators_kobj; -+ -+ enum scst_lun_addr_method addr_method; -+}; -+ -+/* -+ * ACN - access control name. Used to store names, by which -+ * incoming sessions will be assigned to appropriate ACG. -+ */ -+struct scst_acn { -+ struct scst_acg *acg; /* owner ACG */ -+ -+ const char *name; /* initiator's name */ -+ -+ /* List entry in acg->acn_list */ -+ struct list_head acn_list_entry; -+ -+ /* sysfs file attributes */ -+ struct kobj_attribute *acn_attr; -+}; -+ -+/** -+ * struct scst_dev_group - A group of SCST devices (struct scst_device). -+ * -+ * Each device is member of zero or one device groups. With each device group -+ * there are zero or more target groups associated. -+ */ -+struct scst_dev_group { -+ char *name; -+ struct list_head entry; -+ struct list_head dev_list; -+ struct list_head tg_list; -+ struct kobject kobj; -+ struct kobject *dev_kobj; -+ struct kobject *tg_kobj; -+}; -+ -+/** -+ * struct scst_dg_dev - A node in scst_dev_group.dev_list. -+ */ -+struct scst_dg_dev { -+ struct list_head entry; -+ struct scst_device *dev; -+}; -+ -+/** -+ * struct scst_target_group - A group of SCSI targets (struct scst_tgt). -+ * -+ * Such a group is either a primary target port group or a secondary -+ * port group. See also SPC-4 for more information. -+ */ -+struct scst_target_group { -+ struct scst_dev_group *dg; -+ char *name; -+ uint16_t group_id; -+ enum scst_tg_state state; -+ bool preferred; -+ struct list_head entry; -+ struct list_head tgt_list; -+ struct kobject kobj; -+}; -+ -+/** -+ * struct scst_tg_tgt - A node in scst_target_group.tgt_list. -+ * -+ * Such a node can either represent a local storage target (struct scst_tgt) -+ * or a storage target on another system running SCST. In the former case tgt -+ * != NULL and rel_tgt_id is ignored. In the latter case tgt == NULL and -+ * rel_tgt_id is relevant. -+ */ -+struct scst_tg_tgt { -+ struct list_head entry; -+ struct scst_target_group *tg; -+ struct kobject kobj; -+ struct scst_tgt *tgt; -+ char *name; -+ uint16_t rel_tgt_id; -+}; -+ -+/* -+ * Used to store per-session UNIT ATTENTIONs -+ */ -+struct scst_tgt_dev_UA { -+ /* List entry in tgt_dev->UA_list */ -+ struct list_head UA_list_entry; -+ -+ /* Set if UA is global for session */ -+ unsigned short global_UA:1; -+ -+ /* Unit Attention valid sense len */ -+ unsigned short UA_valid_sense_len; -+ /* Unit Attention sense buf */ -+ uint8_t UA_sense_buffer[SCST_SENSE_BUFFERSIZE]; -+}; -+ -+/* Used to deliver AENs */ -+struct scst_aen { -+ int event_fn; /* AEN fn */ -+ -+ struct scst_session *sess; /* corresponding session */ -+ __be64 lun; /* corresponding LUN in SCSI form */ -+ -+ union { -+ /* SCSI AEN data */ -+ struct { -+ int aen_sense_len; -+ uint8_t aen_sense[SCST_STANDARD_SENSE_LEN]; -+ }; -+ }; -+ -+ /* Keeps status of AEN's delivery to remote initiator */ -+ int delivery_status; -+}; -+ -+#ifndef smp_mb__after_set_bit -+/* There is no smp_mb__after_set_bit() in the kernel */ -+#define smp_mb__after_set_bit() smp_mb() -+#endif -+ -+/* -+ * Registers target template. -+ * Returns 0 on success or appropriate error code otherwise. -+ */ -+int __scst_register_target_template(struct scst_tgt_template *vtt, -+ const char *version); -+static inline int scst_register_target_template(struct scst_tgt_template *vtt) -+{ -+ return __scst_register_target_template(vtt, SCST_INTERFACE_VERSION); -+} -+ -+/* -+ * Registers target template, non-GPL version. -+ * Returns 0 on success or appropriate error code otherwise. -+ * -+ * Note: *vtt must be static! -+ */ -+int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt, -+ const char *version); -+static inline int scst_register_target_template_non_gpl( -+ struct scst_tgt_template *vtt) -+{ -+ return __scst_register_target_template_non_gpl(vtt, -+ SCST_INTERFACE_VERSION); -+} -+ -+void scst_unregister_target_template(struct scst_tgt_template *vtt); -+ -+struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt, -+ const char *target_name); -+void scst_unregister_target(struct scst_tgt *tgt); -+ -+struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic, -+ const char *initiator_name, void *tgt_priv, void *result_fn_data, -+ void (*result_fn) (struct scst_session *sess, void *data, int result)); -+struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt, -+ const char *initiator_name, void *tgt_priv); -+void scst_unregister_session(struct scst_session *sess, int wait, -+ void (*unreg_done_fn) (struct scst_session *sess)); -+void scst_unregister_session_non_gpl(struct scst_session *sess); -+ -+int __scst_register_dev_driver(struct scst_dev_type *dev_type, -+ const char *version); -+static inline int scst_register_dev_driver(struct scst_dev_type *dev_type) -+{ -+ return __scst_register_dev_driver(dev_type, SCST_INTERFACE_VERSION); -+} -+void scst_unregister_dev_driver(struct scst_dev_type *dev_type); -+ -+int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type, -+ const char *version); -+/* -+ * Registers dev handler driver for virtual devices (eg VDISK). -+ * Returns 0 on success or appropriate error code otherwise. -+ */ -+static inline int scst_register_virtual_dev_driver( -+ struct scst_dev_type *dev_type) -+{ -+ return __scst_register_virtual_dev_driver(dev_type, -+ SCST_INTERFACE_VERSION); -+} -+ -+void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type); -+ -+bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name); -+ -+struct scst_cmd *scst_rx_cmd(struct scst_session *sess, -+ const uint8_t *lun, int lun_len, const uint8_t *cdb, -+ unsigned int cdb_len, int atomic); -+void scst_cmd_init_done(struct scst_cmd *cmd, -+ enum scst_exec_context pref_context); -+ -+/* -+ * Notifies SCST that the driver finished the first stage of the command -+ * initialization, and the command is ready for execution, but after -+ * SCST done the command's preprocessing preprocessing_done() function -+ * should be called. The second argument sets preferred command execution -+ * context. See SCST_CONTEXT_* constants for details. -+ * -+ * See comment for scst_cmd_init_done() for the serialization requirements. -+ */ -+static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd, -+ enum scst_exec_context pref_context, int set_sn) -+{ -+ cmd->preprocessing_only = 1; -+ cmd->set_sn_on_restart_cmd = !set_sn; -+ scst_cmd_init_done(cmd, pref_context); -+} -+ -+void scst_restart_cmd(struct scst_cmd *cmd, int status, -+ enum scst_exec_context pref_context); -+ -+void scst_rx_data(struct scst_cmd *cmd, int status, -+ enum scst_exec_context pref_context); -+ -+void scst_tgt_cmd_done(struct scst_cmd *cmd, -+ enum scst_exec_context pref_context); -+ -+int scst_rx_mgmt_fn(struct scst_session *sess, -+ const struct scst_rx_mgmt_params *params); -+ -+/* -+ * Creates new management command using tag and sends it for execution. -+ * Can be used for SCST_ABORT_TASK only. -+ * Must not be called in parallel with scst_unregister_session() for the -+ * same sess. Returns 0 for success, error code otherwise. -+ * -+ * Obsolete in favor of scst_rx_mgmt_fn() -+ */ -+static inline int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, -+ uint64_t tag, int atomic, void *tgt_priv) -+{ -+ struct scst_rx_mgmt_params params; -+ -+ BUG_ON(fn != SCST_ABORT_TASK); -+ -+ memset(¶ms, 0, sizeof(params)); -+ params.fn = fn; -+ params.tag = tag; -+ params.tag_set = 1; -+ params.atomic = atomic; -+ params.tgt_priv = tgt_priv; -+ return scst_rx_mgmt_fn(sess, ¶ms); -+} -+ -+/* -+ * Creates new management command using LUN and sends it for execution. -+ * Currently can be used for any fn, except SCST_ABORT_TASK. -+ * Must not be called in parallel with scst_unregister_session() for the -+ * same sess. Returns 0 for success, error code otherwise. -+ * -+ * Obsolete in favor of scst_rx_mgmt_fn() -+ */ -+static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn, -+ const uint8_t *lun, int lun_len, int atomic, void *tgt_priv) -+{ -+ struct scst_rx_mgmt_params params; -+ -+ BUG_ON(fn == SCST_ABORT_TASK); -+ -+ memset(¶ms, 0, sizeof(params)); -+ params.fn = fn; -+ params.lun = lun; -+ params.lun_len = lun_len; -+ params.lun_set = 1; -+ params.atomic = atomic; -+ params.tgt_priv = tgt_priv; -+ return scst_rx_mgmt_fn(sess, ¶ms); -+} -+ -+int scst_get_cdb_info(struct scst_cmd *cmd); -+ -+int scst_set_cmd_error_status(struct scst_cmd *cmd, int status); -+int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq); -+void scst_set_busy(struct scst_cmd *cmd); -+ -+void scst_check_convert_sense(struct scst_cmd *cmd); -+ -+void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq); -+ -+void scst_capacity_data_changed(struct scst_device *dev); -+ -+struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag); -+struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data, -+ int (*cmp_fn) (struct scst_cmd *cmd, -+ void *data)); -+ -+enum dma_data_direction scst_to_dma_dir(int scst_dir); -+enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir); -+ -+/* -+ * Returns true, if cmd's CDB is fully locally handled by SCST and false -+ * otherwise. Dev handlers parse() and dev_done() not called for such commands. -+ */ -+static inline bool scst_is_cmd_fully_local(struct scst_cmd *cmd) -+{ -+ return (cmd->op_flags & SCST_FULLY_LOCAL_CMD) != 0; -+} -+ -+/* -+ * Returns true, if cmd's CDB is locally handled by SCST and -+ * false otherwise. -+ */ -+static inline bool scst_is_cmd_local(struct scst_cmd *cmd) -+{ -+ return (cmd->op_flags & SCST_LOCAL_CMD) != 0; -+} -+ -+/* Returns true, if cmd can deliver UA */ -+static inline bool scst_is_ua_command(struct scst_cmd *cmd) -+{ -+ return (cmd->op_flags & SCST_SKIP_UA) == 0; -+} -+ -+int scst_register_virtual_device(struct scst_dev_type *dev_handler, -+ const char *dev_name); -+void scst_unregister_virtual_device(int id); -+ -+/* -+ * Get/Set functions for tgt's sg_tablesize -+ */ -+static inline int scst_tgt_get_sg_tablesize(struct scst_tgt *tgt) -+{ -+ return tgt->sg_tablesize; -+} -+ -+static inline void scst_tgt_set_sg_tablesize(struct scst_tgt *tgt, int val) -+{ -+ tgt->sg_tablesize = val; -+} -+ -+/* -+ * Get/Set functions for tgt's target private data -+ */ -+static inline void *scst_tgt_get_tgt_priv(struct scst_tgt *tgt) -+{ -+ return tgt->tgt_priv; -+} -+ -+static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val) -+{ -+ tgt->tgt_priv = val; -+} -+ -+void scst_update_hw_pending_start(struct scst_cmd *cmd); -+ -+/* -+ * Get/Set functions for session's target private data -+ */ -+static inline void *scst_sess_get_tgt_priv(struct scst_session *sess) -+{ -+ return sess->tgt_priv; -+} -+ -+static inline void scst_sess_set_tgt_priv(struct scst_session *sess, -+ void *val) -+{ -+ sess->tgt_priv = val; -+} -+ -+uint16_t scst_lookup_tg_id(struct scst_device *dev, struct scst_tgt *tgt); -+bool scst_impl_alua_configured(struct scst_device *dev); -+int scst_tg_get_group_info(void **buf, uint32_t *response_length, -+ struct scst_device *dev, uint8_t data_format); -+ -+/** -+ * Returns TRUE if cmd is being executed in atomic context. -+ * -+ * This function must be used outside of spinlocks and preempt/BH/IRQ -+ * disabled sections, because of the EXTRACHECK in it. -+ */ -+static inline bool scst_cmd_atomic(struct scst_cmd *cmd) -+{ -+ int res = cmd->atomic; -+#ifdef CONFIG_SCST_EXTRACHECKS -+ /* -+ * Checkpatch will complain on the use of in_atomic() below. You -+ * can safely ignore this warning since in_atomic() is used here -+ * only for debugging purposes. -+ */ -+ if (unlikely((in_atomic() || in_interrupt() || irqs_disabled()) && -+ !res)) { -+ printk(KERN_ERR "ERROR: atomic context and non-atomic cmd!\n"); -+ dump_stack(); -+ cmd->atomic = 1; -+ res = 1; -+ } -+#endif -+ return res; -+} -+ -+/* -+ * Returns TRUE if cmd has been preliminary completed, i.e. completed or -+ * aborted. -+ */ -+static inline bool scst_cmd_prelim_completed(struct scst_cmd *cmd) -+{ -+ return cmd->completed || test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags); -+} -+ -+static inline enum scst_exec_context __scst_estimate_context(bool atomic) -+{ -+ if (in_irq()) -+ return SCST_CONTEXT_TASKLET; -+/* -+ * We come here from many non reliable places, like the block layer, and don't -+ * have any reliable way to detect if we called under atomic context or not -+ * (in_atomic() isn't reliable), so let's be safe and disable this section -+ * for now to unconditionally return thread context. -+ */ -+#if 0 -+ else if (irqs_disabled()) -+ return SCST_CONTEXT_THREAD; -+ else if (in_atomic()) -+ return SCST_CONTEXT_DIRECT_ATOMIC; -+ else -+ return atomic ? SCST_CONTEXT_DIRECT : -+ SCST_CONTEXT_DIRECT_ATOMIC; -+#else -+ return SCST_CONTEXT_THREAD; -+#endif -+} -+ -+static inline enum scst_exec_context scst_estimate_context(void) -+{ -+ return __scst_estimate_context(false); -+} -+ -+static inline enum scst_exec_context scst_estimate_context_atomic(void) -+{ -+ return __scst_estimate_context(true); -+} -+ -+/* Returns cmd's CDB */ -+static inline const uint8_t *scst_cmd_get_cdb(struct scst_cmd *cmd) -+{ -+ return cmd->cdb; -+} -+ -+/* Returns cmd's CDB length */ -+static inline unsigned int scst_cmd_get_cdb_len(struct scst_cmd *cmd) -+{ -+ return cmd->cdb_len; -+} -+ -+void scst_cmd_set_ext_cdb(struct scst_cmd *cmd, -+ uint8_t *ext_cdb, unsigned int ext_cdb_len, gfp_t gfp_mask); -+ -+/* Returns cmd's session */ -+static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd) -+{ -+ return cmd->sess; -+} -+ -+/* Returns cmd's response data length */ -+static inline int scst_cmd_get_resp_data_len(struct scst_cmd *cmd) -+{ -+ return cmd->resp_data_len; -+} -+ -+/* Returns cmd's adjusted response data length */ -+static inline int scst_cmd_get_adjusted_resp_data_len(struct scst_cmd *cmd) -+{ -+ return cmd->adjusted_resp_data_len; -+} -+ -+/* Returns if status should be sent for cmd */ -+static inline int scst_cmd_get_is_send_status(struct scst_cmd *cmd) -+{ -+ return cmd->is_send_status; -+} -+ -+/* -+ * Returns pointer to cmd's SG data buffer. -+ * -+ * Usage of this function is not recommended, use scst_get_buf_*() -+ * family of functions instead. -+ */ -+static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd) -+{ -+ return cmd->sg; -+} -+ -+/* -+ * Returns cmd's sg_cnt. -+ * -+ * Usage of this function is not recommended, use scst_get_buf_*() -+ * family of functions instead. -+ */ -+static inline int scst_cmd_get_sg_cnt(struct scst_cmd *cmd) -+{ -+ return cmd->sg_cnt; -+} -+ -+/* -+ * Returns cmd's data buffer length. -+ * -+ * In case if you need to iterate over data in the buffer, usage of -+ * this function is not recommended, use scst_get_buf_*() -+ * family of functions instead. -+ */ -+static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd) -+{ -+ return cmd->bufflen; -+} -+ -+/* -+ * Returns pointer to cmd's bidirectional in (WRITE) SG data buffer. -+ * -+ * Usage of this function is not recommended, use scst_get_out_buf_*() -+ * family of functions instead. -+ */ -+static inline struct scatterlist *scst_cmd_get_out_sg(struct scst_cmd *cmd) -+{ -+ return cmd->out_sg; -+} -+ -+/* -+ * Returns cmd's bidirectional in (WRITE) sg_cnt. -+ * -+ * Usage of this function is not recommended, use scst_get_out_buf_*() -+ * family of functions instead. -+ */ -+static inline int scst_cmd_get_out_sg_cnt(struct scst_cmd *cmd) -+{ -+ return cmd->out_sg_cnt; -+} -+ -+void scst_restore_sg_buff(struct scst_cmd *cmd); -+ -+/* Restores modified sg buffer in the original state, if necessary */ -+static inline void scst_check_restore_sg_buff(struct scst_cmd *cmd) -+{ -+ if (unlikely(cmd->sg_buff_modified)) -+ scst_restore_sg_buff(cmd); -+} -+ -+/* -+ * Returns cmd's bidirectional in (WRITE) data buffer length. -+ * -+ * In case if you need to iterate over data in the buffer, usage of -+ * this function is not recommended, use scst_get_out_buf_*() -+ * family of functions instead. -+ */ -+static inline unsigned int scst_cmd_get_out_bufflen(struct scst_cmd *cmd) -+{ -+ return cmd->out_bufflen; -+} -+ -+/* Returns pointer to cmd's target's SG data buffer */ -+static inline struct scatterlist *scst_cmd_get_tgt_sg(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_sg; -+} -+ -+/* Returns cmd's target's sg_cnt */ -+static inline int scst_cmd_get_tgt_sg_cnt(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_sg_cnt; -+} -+ -+/* Sets cmd's target's SG data buffer */ -+static inline void scst_cmd_set_tgt_sg(struct scst_cmd *cmd, -+ struct scatterlist *sg, int sg_cnt) -+{ -+ cmd->tgt_sg = sg; -+ cmd->tgt_sg_cnt = sg_cnt; -+ cmd->tgt_data_buf_alloced = 1; -+} -+ -+/* Returns pointer to cmd's target's OUT SG data buffer */ -+static inline struct scatterlist *scst_cmd_get_out_tgt_sg(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_out_sg; -+} -+ -+/* Returns cmd's target's OUT sg_cnt */ -+static inline int scst_cmd_get_tgt_out_sg_cnt(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_out_sg_cnt; -+} -+ -+/* Sets cmd's target's OUT SG data buffer */ -+static inline void scst_cmd_set_tgt_out_sg(struct scst_cmd *cmd, -+ struct scatterlist *sg, int sg_cnt) -+{ -+ WARN_ON(!cmd->tgt_data_buf_alloced); -+ -+ cmd->tgt_out_sg = sg; -+ cmd->tgt_out_sg_cnt = sg_cnt; -+} -+ -+/* Returns cmd's data direction */ -+static inline scst_data_direction scst_cmd_get_data_direction( -+ struct scst_cmd *cmd) -+{ -+ return cmd->data_direction; -+} -+ -+/* Returns cmd's write len as well as write SG and sg_cnt */ -+static inline int scst_cmd_get_write_fields(struct scst_cmd *cmd, -+ struct scatterlist **sg, int *sg_cnt) -+{ -+ *sg = *cmd->write_sg; -+ *sg_cnt = *cmd->write_sg_cnt; -+ return cmd->write_len; -+} -+ -+void scst_cmd_set_write_not_received_data_len(struct scst_cmd *cmd, -+ int not_received); -+ -+bool __scst_get_resid(struct scst_cmd *cmd, int *resid, int *bidi_out_resid); -+ -+/* -+ * Returns true if cmd has residual(s) and returns them in the corresponding -+ * parameters(s). -+ */ -+static inline bool scst_get_resid(struct scst_cmd *cmd, -+ int *resid, int *bidi_out_resid) -+{ -+ if (likely(!cmd->resid_possible)) -+ return false; -+ return __scst_get_resid(cmd, resid, bidi_out_resid); -+} -+ -+/* Returns cmd's status byte from host device */ -+static inline uint8_t scst_cmd_get_status(struct scst_cmd *cmd) -+{ -+ return cmd->status; -+} -+ -+/* Returns cmd's status from host adapter itself */ -+static inline uint8_t scst_cmd_get_msg_status(struct scst_cmd *cmd) -+{ -+ return cmd->msg_status; -+} -+ -+/* Returns cmd's status set by low-level driver to indicate its status */ -+static inline uint8_t scst_cmd_get_host_status(struct scst_cmd *cmd) -+{ -+ return cmd->host_status; -+} -+ -+/* Returns cmd's status set by SCSI mid-level */ -+static inline uint8_t scst_cmd_get_driver_status(struct scst_cmd *cmd) -+{ -+ return cmd->driver_status; -+} -+ -+/* Returns pointer to cmd's sense buffer */ -+static inline uint8_t *scst_cmd_get_sense_buffer(struct scst_cmd *cmd) -+{ -+ return cmd->sense; -+} -+ -+/* Returns cmd's valid sense length */ -+static inline int scst_cmd_get_sense_buffer_len(struct scst_cmd *cmd) -+{ -+ return cmd->sense_valid_len; -+} -+ -+/* -+ * Get/Set functions for cmd's queue_type -+ */ -+static inline enum scst_cmd_queue_type scst_cmd_get_queue_type( -+ struct scst_cmd *cmd) -+{ -+ return cmd->queue_type; -+} -+ -+static inline void scst_cmd_set_queue_type(struct scst_cmd *cmd, -+ enum scst_cmd_queue_type queue_type) -+{ -+ cmd->queue_type = queue_type; -+} -+ -+/* -+ * Get/Set functions for cmd's target SN -+ */ -+static inline uint64_t scst_cmd_get_tag(struct scst_cmd *cmd) -+{ -+ return cmd->tag; -+} -+ -+static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint64_t tag) -+{ -+ cmd->tag = tag; -+} -+ -+/* -+ * Get/Set functions for cmd's target private data. -+ * Variant with *_lock must be used if target driver uses -+ * scst_find_cmd() to avoid race with it, except inside scst_find_cmd()'s -+ * callback, where lock is already taken. -+ */ -+static inline void *scst_cmd_get_tgt_priv(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_priv; -+} -+ -+static inline void scst_cmd_set_tgt_priv(struct scst_cmd *cmd, void *val) -+{ -+ cmd->tgt_priv = val; -+} -+ -+/* -+ * Get/Set functions for tgt_need_alloc_data_buf flag -+ */ -+static inline int scst_cmd_get_tgt_need_alloc_data_buf(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_need_alloc_data_buf; -+} -+ -+static inline void scst_cmd_set_tgt_need_alloc_data_buf(struct scst_cmd *cmd) -+{ -+ cmd->tgt_need_alloc_data_buf = 1; -+} -+ -+/* -+ * Get/Set functions for tgt_data_buf_alloced flag -+ */ -+static inline int scst_cmd_get_tgt_data_buff_alloced(struct scst_cmd *cmd) -+{ -+ return cmd->tgt_data_buf_alloced; -+} -+ -+static inline void scst_cmd_set_tgt_data_buff_alloced(struct scst_cmd *cmd) -+{ -+ cmd->tgt_data_buf_alloced = 1; -+} -+ -+/* -+ * Get/Set functions for dh_data_buf_alloced flag -+ */ -+static inline int scst_cmd_get_dh_data_buff_alloced(struct scst_cmd *cmd) -+{ -+ return cmd->dh_data_buf_alloced; -+} -+ -+static inline void scst_cmd_set_dh_data_buff_alloced(struct scst_cmd *cmd) -+{ -+ cmd->dh_data_buf_alloced = 1; -+} -+ -+/* -+ * Get/Set functions for no_sgv flag -+ */ -+static inline int scst_cmd_get_no_sgv(struct scst_cmd *cmd) -+{ -+ return cmd->no_sgv; -+} -+ -+static inline void scst_cmd_set_no_sgv(struct scst_cmd *cmd) -+{ -+ cmd->no_sgv = 1; -+} -+ -+/* -+ * Get/Set functions for tgt_sn -+ */ -+static inline int scst_cmd_get_tgt_sn(struct scst_cmd *cmd) -+{ -+ BUG_ON(!cmd->tgt_sn_set); -+ return cmd->tgt_sn; -+} -+ -+static inline void scst_cmd_set_tgt_sn(struct scst_cmd *cmd, uint32_t tgt_sn) -+{ -+ cmd->tgt_sn_set = 1; -+ cmd->tgt_sn = tgt_sn; -+} -+ -+/* -+ * Get/Set functions for noio_mem_alloc -+ */ -+static inline bool scst_cmd_get_noio_mem_alloc(struct scst_cmd *cmd) -+{ -+ return cmd->noio_mem_alloc; -+} -+ -+static inline void scst_cmd_set_noio_mem_alloc(struct scst_cmd *cmd) -+{ -+ cmd->noio_mem_alloc = 1; -+} -+ -+/* -+ * Returns 1 if the cmd was aborted, so its status is invalid and no -+ * reply shall be sent to the remote initiator. A target driver should -+ * only clear internal resources, associated with cmd. -+ */ -+static inline int scst_cmd_aborted(struct scst_cmd *cmd) -+{ -+ return test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags) && -+ !test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); -+} -+ -+/* Returns sense data format for cmd's dev */ -+static inline bool scst_get_cmd_dev_d_sense(struct scst_cmd *cmd) -+{ -+ return (cmd->dev != NULL) ? cmd->dev->d_sense : 0; -+} -+ -+/* -+ * Get/Set functions for expected data direction, transfer length -+ * and its validity flag -+ */ -+static inline int scst_cmd_is_expected_set(struct scst_cmd *cmd) -+{ -+ return cmd->expected_values_set; -+} -+ -+static inline scst_data_direction scst_cmd_get_expected_data_direction( -+ struct scst_cmd *cmd) -+{ -+ return cmd->expected_data_direction; -+} -+ -+static inline int scst_cmd_get_expected_transfer_len( -+ struct scst_cmd *cmd) -+{ -+ return cmd->expected_transfer_len; -+} -+ -+static inline int scst_cmd_get_expected_out_transfer_len( -+ struct scst_cmd *cmd) -+{ -+ return cmd->expected_out_transfer_len; -+} -+ -+static inline void scst_cmd_set_expected(struct scst_cmd *cmd, -+ scst_data_direction expected_data_direction, -+ int expected_transfer_len) -+{ -+ cmd->expected_data_direction = expected_data_direction; -+ cmd->expected_transfer_len = expected_transfer_len; -+ cmd->expected_values_set = 1; -+} -+ -+static inline void scst_cmd_set_expected_out_transfer_len(struct scst_cmd *cmd, -+ int expected_out_transfer_len) -+{ -+ WARN_ON(!cmd->expected_values_set); -+ cmd->expected_out_transfer_len = expected_out_transfer_len; -+} -+ -+/* -+ * Get/clear functions for cmd's may_need_dma_sync -+ */ -+static inline int scst_get_may_need_dma_sync(struct scst_cmd *cmd) -+{ -+ return cmd->may_need_dma_sync; -+} -+ -+static inline void scst_clear_may_need_dma_sync(struct scst_cmd *cmd) -+{ -+ cmd->may_need_dma_sync = 0; -+} -+ -+/* -+ * Get/set functions for cmd's delivery_status. It is one of -+ * SCST_CMD_DELIVERY_* constants. It specifies the status of the -+ * command's delivery to initiator. -+ */ -+static inline int scst_get_delivery_status(struct scst_cmd *cmd) -+{ -+ return cmd->delivery_status; -+} -+ -+static inline void scst_set_delivery_status(struct scst_cmd *cmd, -+ int delivery_status) -+{ -+ cmd->delivery_status = delivery_status; -+} -+ -+static inline unsigned int scst_get_active_cmd_count(struct scst_cmd *cmd) -+{ -+ if (likely(cmd->tgt_dev != NULL)) -+ return atomic_read(&cmd->tgt_dev->tgt_dev_cmd_count); -+ else -+ return (unsigned int)-1; -+} -+ -+/* -+ * Get/Set function for mgmt cmd's target private data -+ */ -+static inline void *scst_mgmt_cmd_get_tgt_priv(struct scst_mgmt_cmd *mcmd) -+{ -+ return mcmd->tgt_priv; -+} -+ -+static inline void scst_mgmt_cmd_set_tgt_priv(struct scst_mgmt_cmd *mcmd, -+ void *val) -+{ -+ mcmd->tgt_priv = val; -+} -+ -+/* Returns mgmt cmd's completion status (SCST_MGMT_STATUS_* constants) */ -+static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd) -+{ -+ return mcmd->status; -+} -+ -+/* Returns mgmt cmd's TM fn */ -+static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd) -+{ -+ return mcmd->fn; -+} -+ -+/* -+ * Called by dev handler's task_mgmt_fn() to notify SCST core that mcmd -+ * is going to complete asynchronously. -+ */ -+void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd); -+ -+/* -+ * Called by dev handler to notify SCST core that async. mcmd is completed -+ * with status "status". -+ */ -+void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status); -+ -+/* Returns AEN's fn */ -+static inline int scst_aen_get_event_fn(struct scst_aen *aen) -+{ -+ return aen->event_fn; -+} -+ -+/* Returns AEN's session */ -+static inline struct scst_session *scst_aen_get_sess(struct scst_aen *aen) -+{ -+ return aen->sess; -+} -+ -+/* Returns AEN's LUN */ -+static inline __be64 scst_aen_get_lun(struct scst_aen *aen) -+{ -+ return aen->lun; -+} -+ -+/* Returns SCSI AEN's sense */ -+static inline const uint8_t *scst_aen_get_sense(struct scst_aen *aen) -+{ -+ return aen->aen_sense; -+} -+ -+/* Returns SCSI AEN's sense length */ -+static inline int scst_aen_get_sense_len(struct scst_aen *aen) -+{ -+ return aen->aen_sense_len; -+} -+ -+/* -+ * Get/set functions for AEN's delivery_status. It is one of -+ * SCST_AEN_RES_* constants. It specifies the status of the -+ * command's delivery to initiator. -+ */ -+static inline int scst_get_aen_delivery_status(struct scst_aen *aen) -+{ -+ return aen->delivery_status; -+} -+ -+static inline void scst_set_aen_delivery_status(struct scst_aen *aen, -+ int status) -+{ -+ aen->delivery_status = status; -+} -+ -+void scst_aen_done(struct scst_aen *aen); -+ -+static inline void sg_clear(struct scatterlist *sg) -+{ -+ memset(sg, 0, sizeof(*sg)); -+#ifdef CONFIG_DEBUG_SG -+ sg->sg_magic = SG_MAGIC; -+#endif -+} -+ -+enum scst_sg_copy_dir { -+ SCST_SG_COPY_FROM_TARGET, -+ SCST_SG_COPY_TO_TARGET -+}; -+ -+void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir); -+ -+/* -+ * Functions for access to the commands data (SG) buffer. Should be used -+ * instead of direct access. Returns the buffer length for success, 0 for EOD, -+ * negative error code otherwise. -+ * -+ * Never EVER use this function to process only "the first page" of the buffer. -+ * The first SG entry can be as low as few bytes long. Use scst_get_buf_full() -+ * instead for such cases. -+ * -+ * "Buf" argument returns the mapped buffer -+ * -+ * The "put" function unmaps the buffer. -+ */ -+static inline int __scst_get_buf(struct scst_cmd *cmd, int sg_cnt, -+ uint8_t **buf) -+{ -+ int res = 0; -+ struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry; -+ -+ if (cmd->get_sg_buf_entry_num >= sg_cnt) { -+ *buf = NULL; -+ goto out; -+ } -+ -+ if (unlikely(sg_is_chain(sg))) -+ sg = sg_chain_ptr(sg); -+ -+ *buf = page_address(sg_page(sg)); -+ *buf += sg->offset; -+ -+ res = sg->length; -+ -+ cmd->get_sg_buf_entry_num++; -+ cmd->get_sg_buf_cur_sg_entry = ++sg; -+ -+out: -+ return res; -+} -+ -+static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf) -+{ -+ if (unlikely(cmd->sg == NULL)) { -+ *buf = NULL; -+ return 0; -+ } -+ cmd->get_sg_buf_entry_num = 0; -+ cmd->get_sg_buf_cur_sg_entry = cmd->sg; -+ cmd->may_need_dma_sync = 1; -+ return __scst_get_buf(cmd, cmd->sg_cnt, buf); -+} -+ -+static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf) -+{ -+ return __scst_get_buf(cmd, cmd->sg_cnt, buf); -+} -+ -+static inline void scst_put_buf(struct scst_cmd *cmd, void *buf) -+{ -+ /* Nothing to do */ -+} -+ -+static inline int scst_get_out_buf_first(struct scst_cmd *cmd, uint8_t **buf) -+{ -+ if (unlikely(cmd->out_sg == NULL)) { -+ *buf = NULL; -+ return 0; -+ } -+ cmd->get_sg_buf_entry_num = 0; -+ cmd->get_sg_buf_cur_sg_entry = cmd->out_sg; -+ cmd->may_need_dma_sync = 1; -+ return __scst_get_buf(cmd, cmd->out_sg_cnt, buf); -+} -+ -+static inline int scst_get_out_buf_next(struct scst_cmd *cmd, uint8_t **buf) -+{ -+ return __scst_get_buf(cmd, cmd->out_sg_cnt, buf); -+} -+ -+static inline void scst_put_out_buf(struct scst_cmd *cmd, void *buf) -+{ -+ /* Nothing to do */ -+} -+ -+static inline int scst_get_sg_buf_first(struct scst_cmd *cmd, uint8_t **buf, -+ struct scatterlist *sg, int sg_cnt) -+{ -+ if (unlikely(sg == NULL)) { -+ *buf = NULL; -+ return 0; -+ } -+ cmd->get_sg_buf_entry_num = 0; -+ cmd->get_sg_buf_cur_sg_entry = cmd->sg; -+ cmd->may_need_dma_sync = 1; -+ return __scst_get_buf(cmd, sg_cnt, buf); -+} -+ -+static inline int scst_get_sg_buf_next(struct scst_cmd *cmd, uint8_t **buf, -+ struct scatterlist *sg, int sg_cnt) -+{ -+ return __scst_get_buf(cmd, sg_cnt, buf); -+} -+ -+static inline void scst_put_sg_buf(struct scst_cmd *cmd, void *buf, -+ struct scatterlist *sg, int sg_cnt) -+{ -+ /* Nothing to do */ -+} -+ -+/* -+ * Functions for access to the commands data (SG) page. Should be used -+ * instead of direct access. Returns the buffer length for success, 0 for EOD, -+ * negative error code otherwise. -+ * -+ * "Page" argument returns the starting page, "offset" - offset in it. -+ * -+ * The "put" function "puts" the buffer. It should be always be used, because -+ * in future may need to do some additional operations. -+ */ -+static inline int __scst_get_sg_page(struct scst_cmd *cmd, int sg_cnt, -+ struct page **page, int *offset) -+{ -+ int res = 0; -+ struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry; -+ -+ if (cmd->get_sg_buf_entry_num >= sg_cnt) { -+ *page = NULL; -+ *offset = 0; -+ goto out; -+ } -+ -+ if (unlikely(sg_is_chain(sg))) -+ sg = sg_chain_ptr(sg); -+ -+ *page = sg_page(sg); -+ *offset = sg->offset; -+ res = sg->length; -+ -+ cmd->get_sg_buf_entry_num++; -+ cmd->get_sg_buf_cur_sg_entry = ++sg; -+ -+out: -+ return res; -+} -+ -+static inline int scst_get_sg_page_first(struct scst_cmd *cmd, -+ struct page **page, int *offset) -+{ -+ if (unlikely(cmd->sg == NULL)) { -+ *page = NULL; -+ *offset = 0; -+ return 0; -+ } -+ cmd->get_sg_buf_entry_num = 0; -+ cmd->get_sg_buf_cur_sg_entry = cmd->sg; -+ return __scst_get_sg_page(cmd, cmd->sg_cnt, page, offset); -+} -+ -+static inline int scst_get_sg_page_next(struct scst_cmd *cmd, -+ struct page **page, int *offset) -+{ -+ return __scst_get_sg_page(cmd, cmd->sg_cnt, page, offset); -+} -+ -+static inline void scst_put_sg_page(struct scst_cmd *cmd, -+ struct page *page, int offset) -+{ -+ /* Nothing to do */ -+} -+ -+static inline int scst_get_out_sg_page_first(struct scst_cmd *cmd, -+ struct page **page, int *offset) -+{ -+ if (unlikely(cmd->out_sg == NULL)) { -+ *page = NULL; -+ *offset = 0; -+ return 0; -+ } -+ cmd->get_sg_buf_entry_num = 0; -+ cmd->get_sg_buf_cur_sg_entry = cmd->out_sg; -+ return __scst_get_sg_page(cmd, cmd->out_sg_cnt, page, offset); -+} -+ -+static inline int scst_get_out_sg_page_next(struct scst_cmd *cmd, -+ struct page **page, int *offset) -+{ -+ return __scst_get_sg_page(cmd, cmd->out_sg_cnt, page, offset); -+} -+ -+static inline void scst_put_out_sg_page(struct scst_cmd *cmd, -+ struct page *page, int offset) -+{ -+ /* Nothing to do */ -+} -+ -+/* -+ * Returns approximate higher rounded buffers count that -+ * scst_get_buf_[first|next]() return. -+ */ -+static inline int scst_get_buf_count(struct scst_cmd *cmd) -+{ -+ return (cmd->sg_cnt == 0) ? 1 : cmd->sg_cnt; -+} -+ -+/* -+ * Returns approximate higher rounded buffers count that -+ * scst_get_out_buf_[first|next]() return. -+ */ -+static inline int scst_get_out_buf_count(struct scst_cmd *cmd) -+{ -+ return (cmd->out_sg_cnt == 0) ? 1 : cmd->out_sg_cnt; -+} -+ -+int scst_get_buf_full(struct scst_cmd *cmd, uint8_t **buf); -+void scst_put_buf_full(struct scst_cmd *cmd, uint8_t *buf); -+ -+#ifdef CONFIG_DEBUG_LOCK_ALLOC -+extern struct lockdep_map scst_suspend_dep_map; -+#define scst_assert_activity_suspended() \ -+ WARN_ON(debug_locks && !lock_is_held(&scst_suspend_dep_map)); -+#else -+#define scst_assert_activity_suspended() do { } while (0) -+#endif -+int scst_suspend_activity(bool interruptible); -+void scst_resume_activity(void); -+ -+void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic); -+ -+void scst_post_parse(struct scst_cmd *cmd); -+void scst_post_alloc_data_buf(struct scst_cmd *cmd); -+ -+int scst_check_local_events(struct scst_cmd *cmd); -+ -+static inline int scst_pre_check_local_events(struct scst_cmd *cmd) -+{ -+ int res = scst_check_local_events(cmd); -+ cmd->check_local_events_once_done = 1; -+ return res; -+} -+ -+int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd); -+ -+struct scst_trace_log { -+ unsigned int val; -+ const char *token; -+}; -+ -+extern struct mutex scst_mutex; -+ -+const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void); -+ -+/* -+ * Returns target driver's root sysfs kobject. -+ * The driver can create own files/directories/links here. -+ */ -+static inline struct kobject *scst_sysfs_get_tgtt_kobj( -+ struct scst_tgt_template *tgtt) -+{ -+ return &tgtt->tgtt_kobj; -+} -+ -+/* -+ * Returns target's root sysfs kobject. -+ * The driver can create own files/directories/links here. -+ */ -+static inline struct kobject *scst_sysfs_get_tgt_kobj( -+ struct scst_tgt *tgt) -+{ -+ return &tgt->tgt_kobj; -+} -+ -+/* -+ * Returns device handler's root sysfs kobject. -+ * The driver can create own files/directories/links here. -+ */ -+static inline struct kobject *scst_sysfs_get_devt_kobj( -+ struct scst_dev_type *devt) -+{ -+ return &devt->devt_kobj; -+} -+ -+/* -+ * Returns device's root sysfs kobject. -+ * The driver can create own files/directories/links here. -+ */ -+static inline struct kobject *scst_sysfs_get_dev_kobj( -+ struct scst_device *dev) -+{ -+ return &dev->dev_kobj; -+} -+ -+/* -+ * Returns session's root sysfs kobject. -+ * The driver can create own files/directories/links here. -+ */ -+static inline struct kobject *scst_sysfs_get_sess_kobj( -+ struct scst_session *sess) -+{ -+ return &sess->sess_kobj; -+} -+ -+/* Returns target name */ -+static inline const char *scst_get_tgt_name(const struct scst_tgt *tgt) -+{ -+ return tgt->tgt_name; -+} -+ -+int scst_alloc_sense(struct scst_cmd *cmd, int atomic); -+int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic, -+ const uint8_t *sense, unsigned int len); -+ -+int scst_set_sense(uint8_t *buffer, int len, bool d_sense, -+ int key, int asc, int ascq); -+ -+bool scst_is_ua_sense(const uint8_t *sense, int len); -+ -+bool scst_analyze_sense(const uint8_t *sense, int len, -+ unsigned int valid_mask, int key, int asc, int ascq); -+ -+unsigned long scst_random(void); -+ -+void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len); -+ -+void scst_cmd_get(struct scst_cmd *cmd); -+void scst_cmd_put(struct scst_cmd *cmd); -+ -+struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count); -+void scst_free(struct scatterlist *sg, int count); -+ -+void scst_add_thr_data(struct scst_tgt_dev *tgt_dev, -+ struct scst_thr_data_hdr *data, -+ void (*free_fn) (struct scst_thr_data_hdr *data)); -+void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev); -+void scst_dev_del_all_thr_data(struct scst_device *dev); -+struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev, -+ struct task_struct *tsk); -+ -+/* Finds local to the current thread data. Returns NULL, if they not found. */ -+static inline struct scst_thr_data_hdr *scst_find_thr_data( -+ struct scst_tgt_dev *tgt_dev) -+{ -+ return __scst_find_thr_data(tgt_dev, current); -+} -+ -+/* Increase ref counter for the thread data */ -+static inline void scst_thr_data_get(struct scst_thr_data_hdr *data) -+{ -+ atomic_inc(&data->ref); -+} -+ -+/* Decrease ref counter for the thread data */ -+static inline void scst_thr_data_put(struct scst_thr_data_hdr *data) -+{ -+ if (atomic_dec_and_test(&data->ref)) -+ data->free_fn(data); -+} -+ -+int scst_calc_block_shift(int sector_size); -+int scst_sbc_generic_parse(struct scst_cmd *cmd, -+ int (*get_block_shift)(struct scst_cmd *cmd)); -+int scst_cdrom_generic_parse(struct scst_cmd *cmd, -+ int (*get_block_shift)(struct scst_cmd *cmd)); -+int scst_modisk_generic_parse(struct scst_cmd *cmd, -+ int (*get_block_shift)(struct scst_cmd *cmd)); -+int scst_tape_generic_parse(struct scst_cmd *cmd, -+ int (*get_block_size)(struct scst_cmd *cmd)); -+int scst_changer_generic_parse(struct scst_cmd *cmd, -+ int (*nothing)(struct scst_cmd *cmd)); -+int scst_processor_generic_parse(struct scst_cmd *cmd, -+ int (*nothing)(struct scst_cmd *cmd)); -+int scst_raid_generic_parse(struct scst_cmd *cmd, -+ int (*nothing)(struct scst_cmd *cmd)); -+ -+int scst_block_generic_dev_done(struct scst_cmd *cmd, -+ void (*set_block_shift)(struct scst_cmd *cmd, int block_shift)); -+int scst_tape_generic_dev_done(struct scst_cmd *cmd, -+ void (*set_block_size)(struct scst_cmd *cmd, int block_size)); -+ -+int scst_obtain_device_parameters(struct scst_device *dev); -+ -+void scst_reassign_persistent_sess_states(struct scst_session *new_sess, -+ struct scst_session *old_sess); -+ -+int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun); -+ -+/* -+ * Has to be put here open coded, because Linux doesn't have equivalent, which -+ * allows exclusive wake ups of threads in LIFO order. We need it to let (yet) -+ * unneeded threads sleep and not pollute CPU cache by their stacks. -+ */ -+static inline void add_wait_queue_exclusive_head(wait_queue_head_t *q, -+ wait_queue_t *wait) -+{ -+ unsigned long flags; -+ -+ wait->flags |= WQ_FLAG_EXCLUSIVE; -+ spin_lock_irqsave(&q->lock, flags); -+ __add_wait_queue(q, wait); -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+ -+/* -+ * Structure to match events to user space and replies on them -+ */ -+struct scst_sysfs_user_info { -+ /* Unique cookie to identify request */ -+ uint32_t info_cookie; -+ -+ /* Entry in the global list */ -+ struct list_head info_list_entry; -+ -+ /* Set if reply from the user space is being executed */ -+ unsigned int info_being_executed:1; -+ -+ /* Set if this info is in the info_list */ -+ unsigned int info_in_list:1; -+ -+ /* Completion to wait on for the request completion */ -+ struct completion info_completion; -+ -+ /* Request completion status and optional data */ -+ int info_status; -+ void *data; -+}; -+ -+int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info); -+void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info); -+struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie); -+int scst_wait_info_completion(struct scst_sysfs_user_info *info, -+ unsigned long timeout); -+ -+unsigned int scst_get_setup_id(void); -+ -+/* -+ * Needed to avoid potential circular locking dependency between scst_mutex -+ * and internal sysfs locking (s_active). It could be since most sysfs entries -+ * are created and deleted under scst_mutex AND scst_mutex is taken inside -+ * sysfs functions. So, we push from the sysfs functions all the processing -+ * taking scst_mutex. To avoid deadlock, we return from them with EAGAIN -+ * if processing is taking too long. User space then should poll -+ * last_sysfs_mgmt_res until it returns the result of the processing -+ * (something other than EAGAIN). -+ */ -+struct scst_sysfs_work_item { -+ /* -+ * If true, then last_sysfs_mgmt_res will not be updated. This is -+ * needed to allow read only sysfs monitoring during management actions. -+ * All management actions are supposed to be externally serialized, -+ * so then last_sysfs_mgmt_res automatically serialized too. -+ * Otherwise a monitoring action can overwrite value of simultaneous -+ * management action's last_sysfs_mgmt_res. -+ */ -+ bool read_only_action; -+ -+ struct list_head sysfs_work_list_entry; -+ struct kref sysfs_work_kref; -+ int (*sysfs_work_fn)(struct scst_sysfs_work_item *work); -+ struct completion sysfs_work_done; -+ char *buf; -+ -+ union { -+ struct scst_dev_type *devt; -+ struct scst_tgt_template *tgtt; -+ struct { -+ struct scst_tgt *tgt; -+ struct scst_acg *acg; -+ union { -+ bool is_tgt_kobj; -+ int io_grouping_type; -+ bool enable; -+ cpumask_t cpu_mask; -+ }; -+ }; -+ struct { -+ struct scst_device *dev; -+ int new_threads_num; -+ enum scst_dev_type_threads_pool_type new_threads_pool_type; -+ }; -+ struct scst_session *sess; -+ struct { -+ struct scst_tgt *tgt_r; -+ unsigned long rel_tgt_id; -+ }; -+ struct { -+ struct kobject *kobj; -+ }; -+ }; -+ int work_res; -+ char *res_buf; -+}; -+ -+int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *), -+ bool read_only_action, struct scst_sysfs_work_item **res_work); -+int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work); -+void scst_sysfs_work_get(struct scst_sysfs_work_item *work); -+void scst_sysfs_work_put(struct scst_sysfs_work_item *work); -+ -+char *scst_get_next_lexem(char **token_str); -+void scst_restore_token_str(char *prev_lexem, char *token_str); -+char *scst_get_next_token_str(char **input_str); -+ -+void scst_init_threads(struct scst_cmd_threads *cmd_threads); -+void scst_deinit_threads(struct scst_cmd_threads *cmd_threads); -+ -+void scst_pass_through_cmd_done(void *data, char *sense, int result, int resid); -+int scst_scsi_exec_async(struct scst_cmd *cmd, void *data, -+ void (*done)(void *data, char *sense, int result, int resid)); -+ -+#endif /* __SCST_H */ -diff -uprN orig/linux-3.2/include/scst/scst_const.h linux-3.2/include/scst/scst_const.h ---- orig/linux-3.2/include/scst/scst_const.h -+++ linux-3.2/include/scst/scst_const.h -@@ -0,0 +1,487 @@ -+/* -+ * include/scst_const.h -+ * -+ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net> -+ * Copyright (C) 2007 - 2010 ID7 Ltd. -+ * Copyright (C) 2010 - 2011 SCST Ltd. -+ * -+ * Contains common SCST constants. -+ * -+ * 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, version 2 -+ * of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __SCST_CONST_H -+#define __SCST_CONST_H -+ -+#ifndef GENERATING_UPSTREAM_PATCH -+/* -+ * Include <linux/version.h> only when not converting this header file into -+ * a patch for upstream review because only then the symbol LINUX_VERSION_CODE -+ * is needed. -+ */ -+#include <linux/version.h> -+#endif -+#include <scsi/scsi.h> -+ -+/* -+ * Version numbers, the same as for the kernel. -+ * -+ * Changing it don't forget to change SCST_FIO_REV in scst_vdisk.c -+ * and FIO_REV in usr/fileio/common.h as well. -+ */ -+#define SCST_VERSION(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + d) -+#define SCST_VERSION_CODE SCST_VERSION(2, 2, 0, 0) -+#define SCST_VERSION_STRING_SUFFIX -+#define SCST_VERSION_NAME "2.2.0" -+#define SCST_VERSION_STRING SCST_VERSION_NAME SCST_VERSION_STRING_SUFFIX -+ -+#define SCST_CONST_VERSION "$Revision: 3987 $" -+ -+/*** Shared constants between user and kernel spaces ***/ -+ -+/* Max size of CDB */ -+#define SCST_MAX_CDB_SIZE 16 -+ -+/* Max size of long CDB */ -+#define SCST_MAX_LONG_CDB_SIZE 65536 -+ -+/* Max size of various names */ -+#define SCST_MAX_NAME 50 -+ -+/* Max size of external names, like initiator name */ -+#define SCST_MAX_EXTERNAL_NAME 256 -+ -+/* Max LUN. 2 bits are used for addressing method. */ -+#define SCST_MAX_LUN ((1 << (16-2)) - 1) -+ -+/* -+ * Size of sense sufficient to carry standard sense data. -+ * Warning! It's allocated on stack! -+ */ -+#define SCST_STANDARD_SENSE_LEN 18 -+ -+/* Max size of sense */ -+#define SCST_SENSE_BUFFERSIZE 96 -+ -+/************************************************************* -+ ** Allowed delivery statuses for cmd's delivery_status -+ *************************************************************/ -+ -+#define SCST_CMD_DELIVERY_SUCCESS 0 -+#define SCST_CMD_DELIVERY_FAILED -1 -+#define SCST_CMD_DELIVERY_ABORTED -2 -+ -+/************************************************************* -+ ** Values for task management functions -+ *************************************************************/ -+#define SCST_ABORT_TASK 0 -+#define SCST_ABORT_TASK_SET 1 -+#define SCST_CLEAR_ACA 2 -+#define SCST_CLEAR_TASK_SET 3 -+#define SCST_LUN_RESET 4 -+#define SCST_TARGET_RESET 5 -+ -+/** SCST extensions **/ -+ -+/* -+ * Notifies about I_T nexus loss event in the corresponding session. -+ * Aborts all tasks there, resets the reservation, if any, and sets -+ * up the I_T Nexus loss UA. -+ */ -+#define SCST_NEXUS_LOSS_SESS 6 -+ -+/* Aborts all tasks in the corresponding session */ -+#define SCST_ABORT_ALL_TASKS_SESS 7 -+ -+/* -+ * Notifies about I_T nexus loss event. Aborts all tasks in all sessions -+ * of the tgt, resets the reservations, if any, and sets up the I_T Nexus -+ * loss UA. -+ */ -+#define SCST_NEXUS_LOSS 8 -+ -+/* Aborts all tasks in all sessions of the tgt */ -+#define SCST_ABORT_ALL_TASKS 9 -+ -+/* -+ * Internal TM command issued by SCST in scst_unregister_session(). It is the -+ * same as SCST_NEXUS_LOSS_SESS, except: -+ * - it doesn't call task_mgmt_affected_cmds_done() -+ * - it doesn't call task_mgmt_fn_done() -+ * - it doesn't queue NEXUS LOSS UA. -+ * -+ * Target drivers must NEVER use it!! -+ */ -+#define SCST_UNREG_SESS_TM 10 -+ -+/* -+ * Internal TM command issued by SCST in scst_pr_abort_reg(). It aborts all -+ * tasks from mcmd->origin_pr_cmd->tgt_dev, except mcmd->origin_pr_cmd. -+ * Additionally: -+ * - it signals pr_aborting_cmpl completion when all affected -+ * commands marked as aborted. -+ * - it doesn't call task_mgmt_affected_cmds_done() -+ * - it doesn't call task_mgmt_fn_done() -+ * - it calls mcmd->origin_pr_cmd->scst_cmd_done() when all affected -+ * commands aborted. -+ * -+ * Target drivers must NEVER use it!! -+ */ -+#define SCST_PR_ABORT_ALL 11 -+ -+/************************************************************* -+ ** Values for mgmt cmd's status field. Codes taken from iSCSI -+ *************************************************************/ -+#define SCST_MGMT_STATUS_SUCCESS 0 -+#define SCST_MGMT_STATUS_TASK_NOT_EXIST -1 -+#define SCST_MGMT_STATUS_LUN_NOT_EXIST -2 -+#define SCST_MGMT_STATUS_FN_NOT_SUPPORTED -5 -+#define SCST_MGMT_STATUS_REJECTED -255 -+#define SCST_MGMT_STATUS_FAILED -129 -+ -+/************************************************************* -+ ** SCSI LUN addressing methods. See also SAM-2 and the -+ ** section about eight byte LUNs. -+ *************************************************************/ -+enum scst_lun_addr_method { -+ SCST_LUN_ADDR_METHOD_PERIPHERAL = 0, -+ SCST_LUN_ADDR_METHOD_FLAT = 1, -+ SCST_LUN_ADDR_METHOD_LUN = 2, -+ SCST_LUN_ADDR_METHOD_EXTENDED_LUN = 3, -+}; -+ -+/************************************************************* -+ ** SCSI task attribute queue types -+ *************************************************************/ -+enum scst_cmd_queue_type { -+ SCST_CMD_QUEUE_UNTAGGED = 0, -+ SCST_CMD_QUEUE_SIMPLE, -+ SCST_CMD_QUEUE_ORDERED, -+ SCST_CMD_QUEUE_HEAD_OF_QUEUE, -+ SCST_CMD_QUEUE_ACA -+}; -+ -+/************************************************************* -+ ** CDB flags -+ *************************************************************/ -+enum scst_cdb_flags { -+ SCST_TRANSFER_LEN_TYPE_FIXED = 0x0001, -+ SCST_SMALL_TIMEOUT = 0x0002, -+ SCST_LONG_TIMEOUT = 0x0004, -+ SCST_UNKNOWN_LENGTH = 0x0008, -+ SCST_INFO_VALID = 0x0010, /* must be single bit */ -+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x0020, -+ SCST_IMPLICIT_HQ = 0x0040, -+ SCST_SKIP_UA = 0x0080, -+ SCST_WRITE_MEDIUM = 0x0100, -+ SCST_LOCAL_CMD = 0x0200, -+ SCST_FULLY_LOCAL_CMD = 0x0400, -+ SCST_REG_RESERVE_ALLOWED = 0x0800, -+ SCST_WRITE_EXCL_ALLOWED = 0x1000, -+ SCST_EXCL_ACCESS_ALLOWED = 0x2000, -+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ -+ SCST_TEST_IO_IN_SIRQ_ALLOWED = 0x4000, -+#endif -+ SCST_SERIALIZED = 0x8000, -+ SCST_STRICTLY_SERIALIZED = 0x10000|SCST_SERIALIZED, -+}; -+ -+/************************************************************* -+ ** Data direction aliases. Changing it don't forget to change -+ ** scst_to_tgt_dma_dir and SCST_DATA_DIR_MAX as well!! -+ *************************************************************/ -+#define SCST_DATA_UNKNOWN 0 -+#define SCST_DATA_WRITE 1 -+#define SCST_DATA_READ 2 -+#define SCST_DATA_BIDI (SCST_DATA_WRITE | SCST_DATA_READ) -+#define SCST_DATA_NONE 4 -+ -+#define SCST_DATA_DIR_MAX (SCST_DATA_NONE+1) -+ -+/************************************************************* -+ ** Default suffix for targets with NULL names -+ *************************************************************/ -+#define SCST_DEFAULT_TGT_NAME_SUFFIX "_target_" -+ -+/************************************************************* -+ ** Sense manipulation and examination -+ *************************************************************/ -+#define SCST_LOAD_SENSE(key_asc_ascq) key_asc_ascq -+ -+#define SCST_SENSE_VALID(sense) ((sense != NULL) && \ -+ ((((const uint8_t *)(sense))[0] & 0x70) == 0x70)) -+ -+#define SCST_NO_SENSE(sense) ((sense != NULL) && \ -+ (((const uint8_t *)(sense))[2] == 0)) -+ -+/************************************************************* -+ ** Sense data for the appropriate errors. Can be used with -+ ** scst_set_cmd_error() -+ *************************************************************/ -+#define scst_sense_no_sense NO_SENSE, 0x00, 0 -+#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0 -+#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0 -+#define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0 -+#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0 -+#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0 -+#define scst_sense_parameter_value_invalid ILLEGAL_REQUEST, 0x26, 2 -+#define scst_sense_invalid_release ILLEGAL_REQUEST, 0x26, 4 -+#define scst_sense_parameter_list_length_invalid \ -+ ILLEGAL_REQUEST, 0x1A, 0 -+#define scst_sense_reset_UA UNIT_ATTENTION, 0x29, 0 -+#define scst_sense_nexus_loss_UA UNIT_ATTENTION, 0x29, 0x7 -+#define scst_sense_saving_params_unsup ILLEGAL_REQUEST, 0x39, 0 -+#define scst_sense_lun_not_supported ILLEGAL_REQUEST, 0x25, 0 -+#define scst_sense_data_protect DATA_PROTECT, 0x00, 0 -+#define scst_sense_miscompare_error MISCOMPARE, 0x1D, 0 -+#define scst_sense_block_out_range_error ILLEGAL_REQUEST, 0x21, 0 -+#define scst_sense_medium_changed_UA UNIT_ATTENTION, 0x28, 0 -+#define scst_sense_read_error MEDIUM_ERROR, 0x11, 0 -+#define scst_sense_write_error MEDIUM_ERROR, 0x03, 0 -+#define scst_sense_not_ready NOT_READY, 0x04, 0x10 -+#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0 -+#define scst_sense_cleared_by_another_ini_UA UNIT_ATTENTION, 0x2F, 0 -+#define scst_sense_capacity_data_changed UNIT_ATTENTION, 0x2A, 0x9 -+#define scst_sense_reservation_preempted UNIT_ATTENTION, 0x2A, 0x03 -+#define scst_sense_reservation_released UNIT_ATTENTION, 0x2A, 0x04 -+#define scst_sense_registrations_preempted UNIT_ATTENTION, 0x2A, 0x05 -+#define scst_sense_asym_access_state_changed UNIT_ATTENTION, 0x2A, 0x06 -+#define scst_sense_reported_luns_data_changed UNIT_ATTENTION, 0x3F, 0xE -+#define scst_sense_inquery_data_changed UNIT_ATTENTION, 0x3F, 0x3 -+ -+/************************************************************* -+ * SCSI opcodes not listed anywhere else -+ *************************************************************/ -+#define INIT_ELEMENT_STATUS 0x07 -+#define INIT_ELEMENT_STATUS_RANGE 0x37 -+#define PREVENT_ALLOW_MEDIUM 0x1E -+#define REQUEST_VOLUME_ADDRESS 0xB5 -+#define WRITE_VERIFY_16 0x8E -+#define VERIFY_6 0x13 -+#ifndef VERIFY_12 -+#define VERIFY_12 0xAF -+#endif -+#ifndef GENERATING_UPSTREAM_PATCH -+/* -+ * The constants below have been defined in the kernel header <scsi/scsi.h> -+ * and hence are not needed when this header file is included in kernel code. -+ * The definitions below are only used when this header file is included during -+ * compilation of SCST's user space components. -+ */ -+#ifndef READ_16 -+#define READ_16 0x88 -+#endif -+#ifndef WRITE_16 -+#define WRITE_16 0x8a -+#endif -+#ifndef VERIFY_16 -+#define VERIFY_16 0x8f -+#endif -+#ifndef SERVICE_ACTION_IN -+#define SERVICE_ACTION_IN 0x9e -+#endif -+#ifndef SAI_READ_CAPACITY_16 -+/* values for service action in */ -+#define SAI_READ_CAPACITY_16 0x10 -+#endif -+#endif -+#ifndef GENERATING_UPSTREAM_PATCH -+#ifndef REPORT_LUNS -+#define REPORT_LUNS 0xa0 -+#endif -+#endif -+ -+ -+/************************************************************* -+ ** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft -+ ** T10/1561-D Revision 4 Draft dated 7th November 2002. -+ *************************************************************/ -+#define SAM_STAT_GOOD 0x00 -+#define SAM_STAT_CHECK_CONDITION 0x02 -+#define SAM_STAT_CONDITION_MET 0x04 -+#define SAM_STAT_BUSY 0x08 -+#define SAM_STAT_INTERMEDIATE 0x10 -+#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14 -+#define SAM_STAT_RESERVATION_CONFLICT 0x18 -+#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */ -+#define SAM_STAT_TASK_SET_FULL 0x28 -+#define SAM_STAT_ACA_ACTIVE 0x30 -+#define SAM_STAT_TASK_ABORTED 0x40 -+ -+/************************************************************* -+ ** Control byte field in CDB -+ *************************************************************/ -+#define CONTROL_BYTE_LINK_BIT 0x01 -+#define CONTROL_BYTE_NACA_BIT 0x04 -+ -+/************************************************************* -+ ** Byte 1 in INQUIRY CDB -+ *************************************************************/ -+#define SCST_INQ_EVPD 0x01 -+ -+/************************************************************* -+ ** Byte 3 in Standard INQUIRY data -+ *************************************************************/ -+#define SCST_INQ_BYTE3 3 -+ -+#define SCST_INQ_NORMACA_BIT 0x20 -+ -+/************************************************************* -+ ** TPGS field in byte 5 of the INQUIRY response (SPC-4). -+ *************************************************************/ -+enum { -+ SCST_INQ_TPGS_MODE_IMPLICIT = 0x10, -+ SCST_INQ_TPGS_MODE_EXPLICIT = 0x20, -+}; -+ -+/************************************************************* -+ ** Byte 2 in RESERVE_10 CDB -+ *************************************************************/ -+#define SCST_RES_3RDPTY 0x10 -+#define SCST_RES_LONGID 0x02 -+ -+/************************************************************* -+ ** Values for the control mode page TST field -+ *************************************************************/ -+#define SCST_CONTR_MODE_ONE_TASK_SET 0 -+#define SCST_CONTR_MODE_SEP_TASK_SETS 1 -+ -+/******************************************************************* -+ ** Values for the control mode page QUEUE ALGORITHM MODIFIER field -+ *******************************************************************/ -+#define SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER 0 -+#define SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER 1 -+ -+/************************************************************* -+ ** Values for the control mode page D_SENSE field -+ *************************************************************/ -+#define SCST_CONTR_MODE_FIXED_SENSE 0 -+#define SCST_CONTR_MODE_DESCR_SENSE 1 -+ -+/************************************************************* -+ ** TransportID protocol identifiers -+ *************************************************************/ -+ -+#define SCSI_TRANSPORTID_PROTOCOLID_FCP2 0 -+#define SCSI_TRANSPORTID_PROTOCOLID_SPI5 1 -+#define SCSI_TRANSPORTID_PROTOCOLID_SRP 4 -+#define SCSI_TRANSPORTID_PROTOCOLID_ISCSI 5 -+#define SCSI_TRANSPORTID_PROTOCOLID_SAS 6 -+ -+/** -+ * enum scst_tg_state - SCSI target port group asymmetric access state. -+ * -+ * See also the documentation of the REPORT TARGET PORT GROUPS command in SPC-4. -+ */ -+enum scst_tg_state { -+ SCST_TG_STATE_OPTIMIZED = 0x0, -+ SCST_TG_STATE_NONOPTIMIZED = 0x1, -+ SCST_TG_STATE_STANDBY = 0x2, -+ SCST_TG_STATE_UNAVAILABLE = 0x3, -+ SCST_TG_STATE_LBA_DEPENDENT = 0x4, -+ SCST_TG_STATE_OFFLINE = 0xe, -+ SCST_TG_STATE_TRANSITIONING = 0xf, -+}; -+ -+/** -+ * Target port group preferred bit. -+ * -+ * See also the documentation of the REPORT TARGET PORT GROUPS command in SPC-4. -+ */ -+enum { -+ SCST_TG_PREFERRED = 0x80, -+}; -+ -+/** -+ * enum scst_tg_sup - Supported SCSI target port group states. -+ * -+ * See also the documentation of the REPORT TARGET PORT GROUPS command in SPC-4. -+ */ -+enum scst_tg_sup { -+ SCST_TG_SUP_OPTIMIZED = 0x01, -+ SCST_TG_SUP_NONOPTIMIZED = 0x02, -+ SCST_TG_SUP_STANDBY = 0x04, -+ SCST_TG_SUP_UNAVAILABLE = 0x08, -+ SCST_TG_SUP_LBA_DEPENDENT = 0x10, -+ SCST_TG_SUP_OFFLINE = 0x40, -+ SCST_TG_SUP_TRANSITION = 0x80, -+}; -+ -+/************************************************************* -+ ** Misc SCSI constants -+ *************************************************************/ -+#define SCST_SENSE_ASC_UA_RESET 0x29 -+#define BYTCHK 0x02 -+#define POSITION_LEN_SHORT 20 -+#define POSITION_LEN_LONG 32 -+ -+/************************************************************* -+ ** Various timeouts -+ *************************************************************/ -+#define SCST_DEFAULT_TIMEOUT (60 * HZ) -+ -+#define SCST_GENERIC_CHANGER_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_CHANGER_LONG_TIMEOUT (14000 * HZ) -+ -+#define SCST_GENERIC_PROCESSOR_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_PROCESSOR_LONG_TIMEOUT (14000 * HZ) -+ -+#define SCST_GENERIC_TAPE_SMALL_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_TAPE_REG_TIMEOUT (900 * HZ) -+#define SCST_GENERIC_TAPE_LONG_TIMEOUT (14000 * HZ) -+ -+#define SCST_GENERIC_MODISK_SMALL_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_MODISK_REG_TIMEOUT (900 * HZ) -+#define SCST_GENERIC_MODISK_LONG_TIMEOUT (14000 * HZ) -+ -+#define SCST_GENERIC_DISK_SMALL_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_DISK_REG_TIMEOUT (60 * HZ) -+#define SCST_GENERIC_DISK_LONG_TIMEOUT (3600 * HZ) -+ -+#define SCST_GENERIC_RAID_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_RAID_LONG_TIMEOUT (14000 * HZ) -+ -+#define SCST_GENERIC_CDROM_SMALL_TIMEOUT (3 * HZ) -+#define SCST_GENERIC_CDROM_REG_TIMEOUT (900 * HZ) -+#define SCST_GENERIC_CDROM_LONG_TIMEOUT (14000 * HZ) -+ -+#define SCST_MAX_OTHER_TIMEOUT (14000 * HZ) -+ -+/************************************************************* -+ ** I/O grouping attribute string values. Must match constants -+ ** w/o '_STR' suffix! -+ *************************************************************/ -+#define SCST_IO_GROUPING_AUTO_STR "auto" -+#define SCST_IO_GROUPING_THIS_GROUP_ONLY_STR "this_group_only" -+#define SCST_IO_GROUPING_NEVER_STR "never" -+ -+/************************************************************* -+ ** Threads pool type attribute string values. -+ ** Must match scst_dev_type_threads_pool_type! -+ *************************************************************/ -+#define SCST_THREADS_POOL_PER_INITIATOR_STR "per_initiator" -+#define SCST_THREADS_POOL_SHARED_STR "shared" -+ -+/************************************************************* -+ ** Misc constants -+ *************************************************************/ -+#define SCST_SYSFS_BLOCK_SIZE PAGE_SIZE -+ -+#define SCST_PR_DIR "/var/lib/scst/pr" -+ -+#define TID_COMMON_SIZE 24 -+ -+#define SCST_SYSFS_KEY_MARK "[key]" -+ -+#define SCST_MIN_REL_TGT_ID 1 -+#define SCST_MAX_REL_TGT_ID 65535 -+ -+#endif /* __SCST_CONST_H */ -diff -uprN orig/linux-3.2/drivers/scst/scst_main.c linux-3.2/drivers/scst/scst_main.c ---- orig/linux-3.2/drivers/scst/scst_main.c -+++ linux-3.2/drivers/scst/scst_main.c -@@ -0,0 +1,2229 @@ -+/* -+ * scst_main.c -+ * -+ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net> -+ * Copyright (C) 2004 - 2005 Leonid Stoljar -+ * Copyright (C) 2007 - 2010 ID7 Ltd. -+ * Copyright (C) 2010 - 2011 SCST Ltd. -+ * -+ * 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, version 2 -+ * of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/module.h> -+ -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/slab.h> -+#include <linux/sched.h> -+#include <linux/unistd.h> -+#include <linux/string.h> -+#include <linux/kthread.h> -+#include <linux/delay.h> -+#include <linux/lockdep.h> -+ -+#include <scst/scst.h> -+#include "scst_priv.h" -+#include "scst_mem.h" -+#include "scst_pres.h" -+ -+#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) -+#warning HIGHMEM kernel configurations are fully supported, but not \ -+recommended for performance reasons. Consider changing VMSPLIT \ -+option or use a 64-bit configuration instead. See README file for \ -+details. -+#endif -+ -+/** -+ ** SCST global variables. They are all uninitialized to have their layout in -+ ** memory be exactly as specified. Otherwise compiler puts zero-initialized -+ ** variable separately from nonzero-initialized ones. -+ **/ -+ -+/* -+ * Main SCST mutex. All targets, devices and dev_types management is done -+ * under this mutex. -+ * -+ * It must NOT be used in any works (schedule_work(), etc.), because -+ * otherwise a deadlock (double lock, actually) is possible, e.g., with -+ * scst_user detach_tgt(), which is called under scst_mutex and calls -+ * flush_scheduled_work(). -+ */ -+struct mutex scst_mutex; -+EXPORT_SYMBOL_GPL(scst_mutex); -+ -+/* -+ * Secondary level main mutex, inner for scst_mutex. Needed for -+ * __scst_pr_register_all_tg_pt(), since we can't use scst_mutex there, -+ * because of the circular locking dependency with dev_pr_mutex. -+ */ -+struct mutex scst_mutex2; -+ -+/* Both protected by scst_mutex or scst_mutex2 on read and both on write */ -+struct list_head scst_template_list; -+struct list_head scst_dev_list; -+ -+/* Protected by scst_mutex */ -+struct list_head scst_dev_type_list; -+struct list_head scst_virtual_dev_type_list; -+ -+spinlock_t scst_main_lock; -+ -+static struct kmem_cache *scst_mgmt_cachep; -+mempool_t *scst_mgmt_mempool; -+static struct kmem_cache *scst_mgmt_stub_cachep; -+mempool_t *scst_mgmt_stub_mempool; -+static struct kmem_cache *scst_ua_cachep; -+mempool_t *scst_ua_mempool; -+static struct kmem_cache *scst_sense_cachep; -+mempool_t *scst_sense_mempool; -+static struct kmem_cache *scst_aen_cachep; -+mempool_t *scst_aen_mempool; -+struct kmem_cache *scst_tgtd_cachep; -+struct kmem_cache *scst_sess_cachep; -+struct kmem_cache *scst_acgd_cachep; -+ -+unsigned int scst_setup_id; -+ -+spinlock_t scst_init_lock; -+wait_queue_head_t scst_init_cmd_list_waitQ; -+struct list_head scst_init_cmd_list; -+unsigned int scst_init_poll_cnt; -+ -+struct kmem_cache *scst_cmd_cachep; -+ -+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) -+unsigned long scst_trace_flag; -+#endif -+ -+int scst_max_tasklet_cmd = SCST_DEF_MAX_TASKLET_CMD; -+ -+unsigned long scst_flags; -+ -+struct scst_cmd_threads scst_main_cmd_threads; -+ -+struct scst_percpu_info scst_percpu_infos[NR_CPUS]; -+ -+spinlock_t scst_mcmd_lock; -+struct list_head scst_active_mgmt_cmd_list; -+struct list_head scst_delayed_mgmt_cmd_list; -+wait_queue_head_t scst_mgmt_cmd_list_waitQ; -+ -+wait_queue_head_t scst_mgmt_waitQ; -+spinlock_t scst_mgmt_lock; -+struct list_head scst_sess_init_list; -+struct list_head scst_sess_shut_list; -+ -+wait_queue_head_t scst_dev_cmd_waitQ; -+ -+#ifdef CONFIG_LOCKDEP -+static struct lock_class_key scst_suspend_key; -+struct lockdep_map scst_suspend_dep_map = -+ STATIC_LOCKDEP_MAP_INIT("scst_suspend_activity", &scst_suspend_key); -+#endif -+static struct mutex scst_suspend_mutex; -+/* protected by scst_suspend_mutex */ -+static struct list_head scst_cmd_threads_list; -+ -+int scst_threads; -+static struct task_struct *scst_init_cmd_thread; -+static struct task_struct *scst_mgmt_thread; -+static struct task_struct *scst_mgmt_cmd_thread; -+ -+static int suspend_count; -+ -+static int scst_virt_dev_last_id; /* protected by scst_mutex */ -+ -+cpumask_t default_cpu_mask; -+ -+static unsigned int scst_max_cmd_mem; -+unsigned int scst_max_dev_cmd_mem; -+ -+module_param_named(scst_threads, scst_threads, int, 0); -+MODULE_PARM_DESC(scst_threads, "SCSI target threads count"); -+ -+module_param_named(scst_max_cmd_mem, scst_max_cmd_mem, int, S_IRUGO); -+MODULE_PARM_DESC(scst_max_cmd_mem, "Maximum memory allowed to be consumed by " -+ "all SCSI commands of all devices at any given time in MB"); -+ -+module_param_named(scst_max_dev_cmd_mem, scst_max_dev_cmd_mem, int, S_IRUGO); -+MODULE_PARM_DESC(scst_max_dev_cmd_mem, "Maximum memory allowed to be consumed " -+ "by all SCSI commands of a device at any given time in MB"); -+ -+struct scst_dev_type scst_null_devtype = { -+ .name = "none", -+ .threads_num = -1, -+}; -+ -+static void __scst_resume_activity(void); -+ -+/** -+ * __scst_register_target_template() - register target template. -+ * @vtt: target template -+ * @version: SCST_INTERFACE_VERSION version string to ensure that -+ * SCST core and the target driver use the same version of -+ * the SCST interface -+ * -+ * Description: -+ * Registers a target template and returns 0 on success or appropriate -+ * error code otherwise. -+ * -+ * Target drivers supposed to behave sanely and not call register() -+ * and unregister() randomly simultaneously. -+ */ -+int __scst_register_target_template(struct scst_tgt_template *vtt, -+ const char *version) -+{ -+ int res = 0; -+ struct scst_tgt_template *t; -+ -+ TRACE_ENTRY(); -+ -+ INIT_LIST_HEAD(&vtt->tgt_list); -+ -+ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) { -+ PRINT_ERROR("Incorrect version of target %s", vtt->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (!vtt->detect) { -+ PRINT_ERROR("Target driver %s must have " -+ "detect() method.", vtt->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (!vtt->release) { -+ PRINT_ERROR("Target driver %s must have " -+ "release() method.", vtt->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (!vtt->xmit_response) { -+ PRINT_ERROR("Target driver %s must have " -+ "xmit_response() method.", vtt->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (vtt->get_initiator_port_transport_id == NULL) -+ PRINT_WARNING("Target driver %s doesn't support Persistent " -+ "Reservations", vtt->name); -+ -+ if (vtt->threads_num < 0) { -+ PRINT_ERROR("Wrong threads_num value %d for " -+ "target \"%s\"", vtt->threads_num, -+ vtt->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if ((!vtt->enable_target || !vtt->is_target_enabled) && -+ !vtt->enabled_attr_not_needed) -+ PRINT_WARNING("Target driver %s doesn't have enable_target() " -+ "and/or is_target_enabled() method(s). This is unsafe " -+ "and can lead that initiators connected on the " -+ "initialization time can see an unexpected set of " -+ "devices or no devices at all!", vtt->name); -+ -+ if (((vtt->add_target != NULL) && (vtt->del_target == NULL)) || -+ ((vtt->add_target == NULL) && (vtt->del_target != NULL))) { -+ PRINT_ERROR("Target driver %s must either define both " -+ "add_target() and del_target(), or none.", vtt->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (vtt->rdy_to_xfer == NULL) -+ vtt->rdy_to_xfer_atomic = 1; -+ -+ res = mutex_lock_interruptible(&scst_mutex); -+ if (res != 0) -+ goto out; -+ list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { -+ if (strcmp(t->name, vtt->name) == 0) { -+ PRINT_ERROR("Target driver %s already registered", -+ vtt->name); -+ mutex_unlock(&scst_mutex); -+ goto out_unlock; -+ } -+ } -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_tgtt_sysfs_create(vtt); -+ if (res != 0) -+ goto out; -+ -+ mutex_lock(&scst_mutex); -+ mutex_lock(&scst_mutex2); -+ list_add_tail(&vtt->scst_template_list_entry, &scst_template_list); -+ mutex_unlock(&scst_mutex2); -+ mutex_unlock(&scst_mutex); -+ -+ TRACE_DBG("%s", "Calling target driver's detect()"); -+ res = vtt->detect(vtt); -+ TRACE_DBG("Target driver's detect() returned %d", res); -+ if (res < 0) { -+ PRINT_ERROR("%s", "The detect() routine failed"); -+ res = -EINVAL; -+ goto out_del; -+ } -+ -+ PRINT_INFO("Target template %s registered successfully", vtt->name); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_del: -+ scst_tgtt_sysfs_del(vtt); -+ -+ mutex_lock(&scst_mutex); -+ -+ mutex_lock(&scst_mutex2); -+ list_del(&vtt->scst_template_list_entry); -+ mutex_unlock(&scst_mutex2); -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ goto out; -+} -+EXPORT_SYMBOL_GPL(__scst_register_target_template); -+ -+static int scst_check_non_gpl_target_template(struct scst_tgt_template *vtt) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ if (vtt->task_mgmt_affected_cmds_done || vtt->threads_num || -+ vtt->on_hw_pending_cmd_timeout) { -+ PRINT_ERROR("Not allowed functionality in non-GPL version for " -+ "target template %s", vtt->name); -+ res = -EPERM; -+ goto out; -+ } -+ -+ res = 0; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/** -+ * __scst_register_target_template_non_gpl() - register target template, -+ * non-GPL version -+ * @vtt: target template -+ * @version: SCST_INTERFACE_VERSION version string to ensure that -+ * SCST core and the target driver use the same version of -+ * the SCST interface -+ * -+ * Description: -+ * Registers a target template and returns 0 on success or appropriate -+ * error code otherwise. -+ * -+ * Note: *vtt must be static! -+ */ -+int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt, -+ const char *version) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ res = scst_check_non_gpl_target_template(vtt); -+ if (res != 0) -+ goto out; -+ -+ res = __scst_register_target_template(vtt, version); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+EXPORT_SYMBOL(__scst_register_target_template_non_gpl); -+ -+/** -+ * scst_unregister_target_template() - unregister target template -+ * -+ * Target drivers supposed to behave sanely and not call register() -+ * and unregister() randomly simultaneously. Also it is supposed that -+ * no attempts to create new targets for this vtt will be done in a race -+ * with this function. -+ */ -+void scst_unregister_target_template(struct scst_tgt_template *vtt) -+{ -+ struct scst_tgt *tgt; -+ struct scst_tgt_template *t; -+ int found = 0; -+ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { -+ if (strcmp(t->name, vtt->name) == 0) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ PRINT_ERROR("Target driver %s isn't registered", vtt->name); -+ goto out_err_up; -+ } -+ -+ mutex_lock(&scst_mutex2); -+ list_del(&vtt->scst_template_list_entry); -+ mutex_unlock(&scst_mutex2); -+ -+ /* Wait for outstanding sysfs mgmt calls completed */ -+ while (vtt->tgtt_active_sysfs_works_count > 0) { -+ mutex_unlock(&scst_mutex); -+ msleep(100); -+ mutex_lock(&scst_mutex); -+ } -+ -+restart: -+ list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) { -+ mutex_unlock(&scst_mutex); -+ scst_unregister_target(tgt); -+ mutex_lock(&scst_mutex); -+ goto restart; -+ } -+ -+ mutex_unlock(&scst_mutex); -+ -+ scst_tgtt_sysfs_del(vtt); -+ -+ PRINT_INFO("Target template %s unregistered successfully", vtt->name); -+ -+out: -+ TRACE_EXIT(); -+ return; -+ -+out_err_up: -+ mutex_unlock(&scst_mutex); -+ goto out; -+} -+EXPORT_SYMBOL(scst_unregister_target_template); -+ -+/** -+ * scst_register_target() - register target -+ * -+ * Registers a target for template vtt and returns new target structure on -+ * success or NULL otherwise. -+ */ -+struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt, -+ const char *target_name) -+{ -+ struct scst_tgt *tgt, *t; -+ int rc = 0; -+ -+ TRACE_ENTRY(); -+ -+ rc = scst_alloc_tgt(vtt, &tgt); -+ if (rc != 0) -+ goto out; -+ -+ if (target_name != NULL) { -+ -+ tgt->tgt_name = kstrdup(target_name, GFP_KERNEL); -+ if (tgt->tgt_name == NULL) { -+ PRINT_ERROR("Allocation of tgt name %s failed", -+ target_name); -+ rc = -ENOMEM; -+ goto out_free_tgt; -+ } -+ } else { -+ static int tgt_num; /* protected by scst_mutex */ -+ -+ PRINT_WARNING("Usage of autogenerated SCST target names " -+ "is deprecated and will be removed in one of the next " -+ "versions. It is strongly recommended to update target " -+ "driver %s to use hardware related persistent target " -+ "names instead", vtt->name); -+ -+ tgt->tgt_name = kasprintf(GFP_KERNEL, "%s%s%d", vtt->name, -+ SCST_DEFAULT_TGT_NAME_SUFFIX, tgt_num); -+ if (tgt->tgt_name == NULL) { -+ PRINT_ERROR("Allocation of tgt name failed " -+ "(template name %s)", vtt->name); -+ rc = -ENOMEM; -+ goto out_free_tgt; -+ } -+ tgt_num++; -+ } -+ -+ rc = mutex_lock_interruptible(&scst_mutex); -+ if (rc != 0) -+ goto out_free_tgt; -+ -+ list_for_each_entry(t, &vtt->tgt_list, tgt_list_entry) { -+ if (strcmp(t->tgt_name, tgt->tgt_name) == 0) { -+ PRINT_ERROR("target %s already exists", tgt->tgt_name); -+ rc = -EEXIST; -+ goto out_unlock; -+ } -+ } -+ -+ rc = scst_tgt_sysfs_create(tgt); -+ if (rc < 0) -+ goto out_unlock; -+ -+ tgt->default_acg = scst_alloc_add_acg(tgt, tgt->tgt_name, false); -+ if (tgt->default_acg == NULL) -+ goto out_sysfs_del; -+ -+ mutex_lock(&scst_mutex2); -+ list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list); -+ mutex_unlock(&scst_mutex2); -+ -+ mutex_unlock(&scst_mutex); -+ -+ PRINT_INFO("Target %s for template %s registered successfully", -+ tgt->tgt_name, vtt->name); -+ -+ TRACE_DBG("tgt %p", tgt); -+ -+out: -+ TRACE_EXIT(); -+ return tgt; -+ -+out_sysfs_del: -+ mutex_unlock(&scst_mutex); -+ scst_tgt_sysfs_del(tgt); -+ goto out_free_tgt; -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ -+out_free_tgt: -+ /* In case of error tgt_name will be freed in scst_free_tgt() */ -+ scst_free_tgt(tgt); -+ tgt = NULL; -+ goto out; -+} -+EXPORT_SYMBOL(scst_register_target); -+ -+static inline int test_sess_list(struct scst_tgt *tgt) -+{ -+ int res; -+ mutex_lock(&scst_mutex); -+ res = list_empty(&tgt->sess_list); -+ mutex_unlock(&scst_mutex); -+ return res; -+} -+ -+/** -+ * scst_unregister_target() - unregister target. -+ * -+ * It is supposed that no attempts to create new sessions for this -+ * target will be done in a race with this function. -+ */ -+void scst_unregister_target(struct scst_tgt *tgt) -+{ -+ struct scst_session *sess; -+ struct scst_tgt_template *vtt = tgt->tgtt; -+ struct scst_acg *acg, *acg_tmp; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_DBG("%s", "Calling target driver's release()"); -+ tgt->tgtt->release(tgt); -+ TRACE_DBG("%s", "Target driver's release() returned"); -+ -+ mutex_lock(&scst_mutex); -+again: -+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { -+ if (sess->shut_phase == SCST_SESS_SPH_READY) { -+ /* -+ * Sometimes it's hard for target driver to track all -+ * its sessions (see scst_local, eg), so let's help it. -+ */ -+ mutex_unlock(&scst_mutex); -+ scst_unregister_session(sess, 0, NULL); -+ mutex_lock(&scst_mutex); -+ goto again; -+ } -+ } -+ mutex_unlock(&scst_mutex); -+ -+ TRACE_DBG("%s", "Waiting for sessions shutdown"); -+ wait_event(tgt->unreg_waitQ, test_sess_list(tgt)); -+ TRACE_DBG("%s", "wait_event() returned"); -+ -+ scst_suspend_activity(false); -+ mutex_lock(&scst_mutex); -+ -+ mutex_lock(&scst_mutex2); -+ list_del(&tgt->tgt_list_entry); -+ mutex_unlock(&scst_mutex2); -+ -+ del_timer_sync(&tgt->retry_timer); -+ -+ scst_tg_tgt_remove_by_tgt(tgt); -+ -+ scst_del_free_acg(tgt->default_acg); -+ -+ list_for_each_entry_safe(acg, acg_tmp, &tgt->tgt_acg_list, -+ acg_list_entry) { -+ scst_del_free_acg(acg); -+ } -+ -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ -+ scst_tgt_sysfs_del(tgt); -+ -+ PRINT_INFO("Target %s for template %s unregistered successfully", -+ tgt->tgt_name, vtt->name); -+ -+ scst_free_tgt(tgt); -+ -+ TRACE_DBG("Unregistering tgt %p finished", tgt); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL(scst_unregister_target); -+ -+int scst_get_cmd_counter(void) -+{ -+ int i, res = 0; -+ for (i = 0; i < (int)ARRAY_SIZE(scst_percpu_infos); i++) -+ res += atomic_read(&scst_percpu_infos[i].cpu_cmd_count); -+ return res; -+} -+ -+static int scst_susp_wait(bool interruptible) -+{ -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ if (interruptible) { -+ res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ, -+ (scst_get_cmd_counter() == 0), -+ SCST_SUSPENDING_TIMEOUT); -+ if (res <= 0) { -+ __scst_resume_activity(); -+ if (res == 0) -+ res = -EBUSY; -+ } else -+ res = 0; -+ } else -+ wait_event(scst_dev_cmd_waitQ, scst_get_cmd_counter() == 0); -+ -+ TRACE_MGMT_DBG("wait_event() returned %d", res); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/** -+ * scst_suspend_activity() - globally suspend any activity -+ * -+ * Description: -+ * Globally suspends any activity and doesn't return, until there are any -+ * active commands (state after SCST_CMD_STATE_INIT). If "interruptible" -+ * is true, it returns after SCST_SUSPENDING_TIMEOUT or if it was interrupted -+ * by a signal with the corresponding error status < 0. If "interruptible" -+ * is false, it will wait virtually forever. On success returns 0. -+ * -+ * New arriving commands stay in the suspended state until -+ * scst_resume_activity() is called. -+ */ -+int scst_suspend_activity(bool interruptible) -+{ -+ int res = 0; -+ bool rep = false; -+ -+ TRACE_ENTRY(); -+ -+ rwlock_acquire_read(&scst_suspend_dep_map, 0, 0, _RET_IP_); -+ -+ if (interruptible) { -+ if (mutex_lock_interruptible(&scst_suspend_mutex) != 0) { -+ res = -EINTR; -+ goto out; -+ } -+ } else -+ mutex_lock(&scst_suspend_mutex); -+ -+ TRACE_MGMT_DBG("suspend_count %d", suspend_count); -+ suspend_count++; -+ if (suspend_count > 1) -+ goto out_up; -+ -+ set_bit(SCST_FLAG_SUSPENDING, &scst_flags); -+ set_bit(SCST_FLAG_SUSPENDED, &scst_flags); -+ /* -+ * Assignment of SCST_FLAG_SUSPENDING and SCST_FLAG_SUSPENDED must be -+ * ordered with cpu_cmd_count in scst_get(). Otherwise lockless logic in -+ * scst_translate_lun() and scst_mgmt_translate_lun() won't work. -+ */ -+ smp_mb__after_set_bit(); -+ -+ /* -+ * See comment in scst_user.c::dev_user_task_mgmt_fn() for more -+ * information about scst_user behavior. -+ * -+ * ToDo: make the global suspending unneeded (switch to per-device -+ * reference counting? That would mean to switch off from lockless -+ * implementation of scst_translate_lun().. ) -+ */ -+ -+ if (scst_get_cmd_counter() != 0) { -+ PRINT_INFO("Waiting for %d active commands to complete... This " -+ "might take few minutes for disks or few hours for " -+ "tapes, if you use long executed commands, like " -+ "REWIND or FORMAT. In case, if you have a hung user " -+ "space device (i.e. made using scst_user module) not " -+ "responding to any commands, if might take virtually " -+ "forever until the corresponding user space " -+ "program recovers and starts responding or gets " -+ "killed.", scst_get_cmd_counter()); -+ rep = true; -+ -+ lock_contended(&scst_suspend_dep_map, _RET_IP_); -+ } -+ -+ res = scst_susp_wait(interruptible); -+ if (res != 0) -+ goto out_clear; -+ -+ clear_bit(SCST_FLAG_SUSPENDING, &scst_flags); -+ /* See comment about smp_mb() above */ -+ smp_mb__after_clear_bit(); -+ -+ TRACE_MGMT_DBG("Waiting for %d active commands finally to complete", -+ scst_get_cmd_counter()); -+ -+ res = scst_susp_wait(interruptible); -+ if (res != 0) -+ goto out_clear; -+ -+ if (rep) -+ PRINT_INFO("%s", "All active commands completed"); -+ -+out_up: -+ mutex_unlock(&scst_suspend_mutex); -+ -+out: -+ if (res == 0) -+ lock_acquired(&scst_suspend_dep_map, _RET_IP_); -+ else -+ rwlock_release(&scst_suspend_dep_map, 1, _RET_IP_); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_clear: -+ clear_bit(SCST_FLAG_SUSPENDING, &scst_flags); -+ /* See comment about smp_mb() above */ -+ smp_mb__after_clear_bit(); -+ goto out_up; -+} -+EXPORT_SYMBOL_GPL(scst_suspend_activity); -+ -+static void __scst_resume_activity(void) -+{ -+ struct scst_cmd_threads *l; -+ -+ TRACE_ENTRY(); -+ -+ suspend_count--; -+ TRACE_MGMT_DBG("suspend_count %d left", suspend_count); -+ if (suspend_count > 0) -+ goto out; -+ -+ clear_bit(SCST_FLAG_SUSPENDED, &scst_flags); -+ /* -+ * The barrier is needed to make sure all woken up threads see the -+ * cleared flag. Not sure if it's really needed, but let's be safe. -+ */ -+ smp_mb__after_clear_bit(); -+ -+ list_for_each_entry(l, &scst_cmd_threads_list, lists_list_entry) { -+ wake_up_all(&l->cmd_list_waitQ); -+ } -+ wake_up_all(&scst_init_cmd_list_waitQ); -+ -+ spin_lock_irq(&scst_mcmd_lock); -+ if (!list_empty(&scst_delayed_mgmt_cmd_list)) { -+ struct scst_mgmt_cmd *m; -+ m = list_entry(scst_delayed_mgmt_cmd_list.next, typeof(*m), -+ mgmt_cmd_list_entry); -+ TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active " -+ "mgmt cmd list", m); -+ list_move(&m->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list); -+ } -+ spin_unlock_irq(&scst_mcmd_lock); -+ wake_up_all(&scst_mgmt_cmd_list_waitQ); -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+ -+/** -+ * scst_resume_activity() - globally resume all activities -+ * -+ * Resumes suspended by scst_suspend_activity() activities. -+ */ -+void scst_resume_activity(void) -+{ -+ TRACE_ENTRY(); -+ -+ rwlock_release(&scst_suspend_dep_map, 1, _RET_IP_); -+ -+ mutex_lock(&scst_suspend_mutex); -+ __scst_resume_activity(); -+ mutex_unlock(&scst_suspend_mutex); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_resume_activity); -+ -+static int scst_register_device(struct scsi_device *scsidp) -+{ -+ int res; -+ struct scst_device *dev, *d; -+ -+ TRACE_ENTRY(); -+ -+ res = mutex_lock_interruptible(&scst_mutex); -+ if (res != 0) -+ goto out; -+ -+ res = scst_alloc_device(GFP_KERNEL, &dev); -+ if (res != 0) -+ goto out_unlock; -+ -+ dev->type = scsidp->type; -+ -+ dev->virt_name = kasprintf(GFP_KERNEL, "%d:%d:%d:%d", -+ scsidp->host->host_no, -+ scsidp->channel, scsidp->id, scsidp->lun); -+ if (dev->virt_name == NULL) { -+ PRINT_ERROR("%s", "Unable to alloc device name"); -+ res = -ENOMEM; -+ goto out_free_dev; -+ } -+ -+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) { -+ if (strcmp(d->virt_name, dev->virt_name) == 0) { -+ PRINT_ERROR("Device %s already exists", dev->virt_name); -+ res = -EEXIST; -+ goto out_free_dev; -+ } -+ } -+ -+ dev->scsi_dev = scsidp; -+ -+ list_add_tail(&dev->dev_list_entry, &scst_dev_list); -+ -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_dev_sysfs_create(dev); -+ if (res != 0) -+ goto out_del; -+ -+ PRINT_INFO("Attached to scsi%d, channel %d, id %d, lun %d, " -+ "type %d", scsidp->host->host_no, scsidp->channel, -+ scsidp->id, scsidp->lun, scsidp->type); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_del: -+ list_del(&dev->dev_list_entry); -+ -+out_free_dev: -+ scst_free_device(dev); -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ goto out; -+} -+ -+static void scst_unregister_device(struct scsi_device *scsidp) -+{ -+ struct scst_device *d, *dev = NULL; -+ struct scst_acg_dev *acg_dev, *aa; -+ -+ TRACE_ENTRY(); -+ -+ scst_suspend_activity(false); -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) { -+ if (d->scsi_dev == scsidp) { -+ dev = d; -+ TRACE_DBG("Device %p found", dev); -+ break; -+ } -+ } -+ if (dev == NULL) { -+ PRINT_ERROR("SCST device for SCSI device %d:%d:%d:%d not found", -+ scsidp->host->host_no, scsidp->channel, scsidp->id, -+ scsidp->lun); -+ goto out_unlock; -+ } -+ -+ dev->dev_unregistering = 1; -+ -+ list_del(&dev->dev_list_entry); -+ -+ scst_dg_dev_remove_by_dev(dev); -+ -+ scst_assign_dev_handler(dev, &scst_null_devtype); -+ -+ list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list, -+ dev_acg_dev_list_entry) { -+ scst_acg_del_lun(acg_dev->acg, acg_dev->lun, true); -+ } -+ -+ mutex_unlock(&scst_mutex); -+ -+ scst_resume_activity(); -+ -+ scst_dev_sysfs_del(dev); -+ -+ PRINT_INFO("Detached from scsi%d, channel %d, id %d, lun %d, type %d", -+ scsidp->host->host_no, scsidp->channel, scsidp->id, -+ scsidp->lun, scsidp->type); -+ -+ scst_free_device(dev); -+ -+out: -+ TRACE_EXIT(); -+ return; -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ goto out; -+} -+ -+static int scst_dev_handler_check(struct scst_dev_type *dev_handler) -+{ -+ int res = 0; -+ -+ if (dev_handler->parse == NULL) { -+ PRINT_ERROR("scst dev handler %s must have " -+ "parse() method.", dev_handler->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (((dev_handler->add_device != NULL) && -+ (dev_handler->del_device == NULL)) || -+ ((dev_handler->add_device == NULL) && -+ (dev_handler->del_device != NULL))) { -+ PRINT_ERROR("Dev handler %s must either define both " -+ "add_device() and del_device(), or none.", -+ dev_handler->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (dev_handler->alloc_data_buf == NULL) -+ dev_handler->alloc_data_buf_atomic = 1; -+ -+ if (dev_handler->dev_done == NULL) -+ dev_handler->dev_done_atomic = 1; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_check_device_name(const char *dev_name) -+{ -+ int res = 0; -+ -+ if (strchr(dev_name, '/') != NULL) { -+ PRINT_ERROR("Dev name %s contains illegal character '/'", -+ dev_name); -+ res = -EINVAL; -+ } -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/** -+ * scst_register_virtual_device() - register a virtual device. -+ * @dev_handler: the device's device handler -+ * @dev_name: the new device name, NULL-terminated string. Must be uniq -+ * among all virtual devices in the system. -+ * -+ * Registers a virtual device and returns ID assigned to the device on -+ * success, or negative value otherwise -+ */ -+int scst_register_virtual_device(struct scst_dev_type *dev_handler, -+ const char *dev_name) -+{ -+ int res; -+ struct scst_device *dev, *d; -+ bool sysfs_del = false; -+ -+ TRACE_ENTRY(); -+ -+ if (dev_handler == NULL) { -+ PRINT_ERROR("%s: valid device handler must be supplied", -+ __func__); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ if (dev_name == NULL) { -+ PRINT_ERROR("%s: device name must be non-NULL", __func__); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ res = scst_check_device_name(dev_name); -+ if (res != 0) -+ goto out; -+ -+ res = scst_dev_handler_check(dev_handler); -+ if (res != 0) -+ goto out; -+ -+ res = scst_suspend_activity(true); -+ if (res != 0) -+ goto out; -+ -+ res = mutex_lock_interruptible(&scst_mutex); -+ if (res != 0) -+ goto out_resume; -+ -+ res = scst_alloc_device(GFP_KERNEL, &dev); -+ if (res != 0) -+ goto out_unlock; -+ -+ dev->type = dev_handler->type; -+ dev->scsi_dev = NULL; -+ dev->virt_name = kstrdup(dev_name, GFP_KERNEL); -+ if (dev->virt_name == NULL) { -+ PRINT_ERROR("Unable to allocate virt_name for dev %s", -+ dev_name); -+ res = -ENOMEM; -+ goto out_free_dev; -+ } -+ -+ while (1) { -+ dev->virt_id = scst_virt_dev_last_id++; -+ if (dev->virt_id > 0) -+ break; -+ scst_virt_dev_last_id = 1; -+ } -+ -+ res = dev->virt_id; -+ -+ res = scst_pr_init_dev(dev); -+ if (res != 0) -+ goto out_free_dev; -+ -+ /* -+ * We can drop scst_mutex, because we have not yet added the dev in -+ * scst_dev_list, so it "doesn't exist" yet. -+ */ -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_dev_sysfs_create(dev); -+ if (res != 0) -+ goto out_lock_pr_clear_dev; -+ -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) { -+ if (strcmp(d->virt_name, dev_name) == 0) { -+ PRINT_ERROR("Device %s already exists", dev_name); -+ res = -EEXIST; -+ sysfs_del = true; -+ goto out_pr_clear_dev; -+ } -+ } -+ -+ res = scst_assign_dev_handler(dev, dev_handler); -+ if (res != 0) { -+ sysfs_del = true; -+ goto out_pr_clear_dev; -+ } -+ -+ list_add_tail(&dev->dev_list_entry, &scst_dev_list); -+ -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ -+ res = dev->virt_id; -+ -+ PRINT_INFO("Attached to virtual device %s (id %d)", dev_name, res); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_lock_pr_clear_dev: -+ mutex_lock(&scst_mutex); -+ -+out_pr_clear_dev: -+ scst_pr_clear_dev(dev); -+ -+out_free_dev: -+ mutex_unlock(&scst_mutex); -+ if (sysfs_del) -+ scst_dev_sysfs_del(dev); -+ scst_free_device(dev); -+ goto out_resume; -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ -+out_resume: -+ scst_resume_activity(); -+ goto out; -+} -+EXPORT_SYMBOL_GPL(scst_register_virtual_device); -+ -+/** -+ * scst_unregister_virtual_device() - unegister a virtual device. -+ * @id: the device's ID, returned by the registration function -+ */ -+void scst_unregister_virtual_device(int id) -+{ -+ struct scst_device *d, *dev = NULL; -+ struct scst_acg_dev *acg_dev, *aa; -+ -+ TRACE_ENTRY(); -+ -+ scst_suspend_activity(false); -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) { -+ if (d->virt_id == id) { -+ dev = d; -+ TRACE_DBG("Virtual device %p (id %d) found", dev, id); -+ break; -+ } -+ } -+ if (dev == NULL) { -+ PRINT_ERROR("Virtual device (id %d) not found", id); -+ goto out_unlock; -+ } -+ -+ dev->dev_unregistering = 1; -+ -+ list_del(&dev->dev_list_entry); -+ -+ scst_pr_clear_dev(dev); -+ -+ scst_dg_dev_remove_by_dev(dev); -+ -+ scst_assign_dev_handler(dev, &scst_null_devtype); -+ -+ list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list, -+ dev_acg_dev_list_entry) { -+ scst_acg_del_lun(acg_dev->acg, acg_dev->lun, true); -+ } -+ -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ -+ scst_dev_sysfs_del(dev); -+ -+ PRINT_INFO("Detached from virtual device %s (id %d)", -+ dev->virt_name, dev->virt_id); -+ -+ scst_free_device(dev); -+ -+out: -+ TRACE_EXIT(); -+ return; -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ goto out; -+} -+EXPORT_SYMBOL_GPL(scst_unregister_virtual_device); -+ -+/** -+ * __scst_register_dev_driver() - register pass-through dev handler driver -+ * @dev_type: dev handler template -+ * @version: SCST_INTERFACE_VERSION version string to ensure that -+ * SCST core and the dev handler use the same version of -+ * the SCST interface -+ * -+ * Description: -+ * Registers a pass-through dev handler driver. Returns 0 on success -+ * or appropriate error code otherwise. -+ */ -+int __scst_register_dev_driver(struct scst_dev_type *dev_type, -+ const char *version) -+{ -+ int res, exist; -+ struct scst_dev_type *dt; -+ -+ TRACE_ENTRY(); -+ -+ res = -EINVAL; -+ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) { -+ PRINT_ERROR("Incorrect version of dev handler %s", -+ dev_type->name); -+ goto out; -+ } -+ -+ res = scst_dev_handler_check(dev_type); -+ if (res != 0) -+ goto out; -+ -+ res = mutex_lock_interruptible(&scst_mutex); -+ if (res != 0) -+ goto out; -+ -+ exist = 0; -+ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { -+ if (strcmp(dt->name, dev_type->name) == 0) { -+ PRINT_ERROR("Device type handler \"%s\" already " -+ "exists", dt->name); -+ exist = 1; -+ break; -+ } -+ } -+ if (exist) -+ goto out_unlock; -+ -+ list_add_tail(&dev_type->dev_type_list_entry, &scst_dev_type_list); -+ -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_devt_sysfs_create(dev_type); -+ if (res < 0) -+ goto out; -+ -+ PRINT_INFO("Device handler \"%s\" for type %d registered " -+ "successfully", dev_type->name, dev_type->type); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ goto out; -+} -+EXPORT_SYMBOL_GPL(__scst_register_dev_driver); -+ -+/** -+ * scst_unregister_dev_driver() - unregister pass-through dev handler driver -+ */ -+void scst_unregister_dev_driver(struct scst_dev_type *dev_type) -+{ -+ struct scst_device *dev; -+ struct scst_dev_type *dt; -+ int found = 0; -+ -+ TRACE_ENTRY(); -+ -+ scst_suspend_activity(false); -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { -+ if (strcmp(dt->name, dev_type->name) == 0) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ PRINT_ERROR("Dev handler \"%s\" isn't registered", -+ dev_type->name); -+ goto out_up; -+ } -+ -+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { -+ if (dev->handler == dev_type) { -+ scst_assign_dev_handler(dev, &scst_null_devtype); -+ TRACE_DBG("Dev handler removed from device %p", dev); -+ } -+ } -+ -+ list_del(&dev_type->dev_type_list_entry); -+ -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ -+ scst_devt_sysfs_del(dev_type); -+ -+ PRINT_INFO("Device handler \"%s\" for type %d unloaded", -+ dev_type->name, dev_type->type); -+ -+out: -+ TRACE_EXIT(); -+ return; -+ -+out_up: -+ mutex_unlock(&scst_mutex); -+ scst_resume_activity(); -+ goto out; -+} -+EXPORT_SYMBOL_GPL(scst_unregister_dev_driver); -+ -+/** -+ * __scst_register_virtual_dev_driver() - register virtual dev handler driver -+ * @dev_type: dev handler template -+ * @version: SCST_INTERFACE_VERSION version string to ensure that -+ * SCST core and the dev handler use the same version of -+ * the SCST interface -+ * -+ * Description: -+ * Registers a virtual dev handler driver. Returns 0 on success or -+ * appropriate error code otherwise. -+ */ -+int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type, -+ const char *version) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) { -+ PRINT_ERROR("Incorrect version of virtual dev handler %s", -+ dev_type->name); -+ res = -EINVAL; -+ goto out; -+ } -+ -+ res = scst_dev_handler_check(dev_type); -+ if (res != 0) -+ goto out; -+ -+ res = mutex_lock_interruptible(&scst_mutex); -+ if (res != 0) -+ goto out; -+ list_add_tail(&dev_type->dev_type_list_entry, &scst_virtual_dev_type_list); -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_devt_sysfs_create(dev_type); -+ if (res < 0) -+ goto out; -+ -+ if (dev_type->type != -1) { -+ PRINT_INFO("Virtual device handler %s for type %d " -+ "registered successfully", dev_type->name, -+ dev_type->type); -+ } else { -+ PRINT_INFO("Virtual device handler \"%s\" registered " -+ "successfully", dev_type->name); -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+EXPORT_SYMBOL_GPL(__scst_register_virtual_dev_driver); -+ -+/** -+ * scst_unregister_virtual_dev_driver() - unregister virtual dev driver -+ */ -+void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type) -+{ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ /* Disable sysfs mgmt calls (e.g. addition of new devices) */ -+ list_del(&dev_type->dev_type_list_entry); -+ -+ /* Wait for outstanding sysfs mgmt calls completed */ -+ while (dev_type->devt_active_sysfs_works_count > 0) { -+ mutex_unlock(&scst_mutex); -+ msleep(100); -+ mutex_lock(&scst_mutex); -+ } -+ -+ mutex_unlock(&scst_mutex); -+ -+ scst_devt_sysfs_del(dev_type); -+ -+ PRINT_INFO("Device handler \"%s\" unloaded", dev_type->name); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_unregister_virtual_dev_driver); -+ -+/* scst_mutex supposed to be held */ -+int scst_add_threads(struct scst_cmd_threads *cmd_threads, -+ struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num) -+{ -+ int res = 0, i; -+ struct scst_cmd_thread_t *thr; -+ int n = 0, tgt_dev_num = 0; -+ -+ TRACE_ENTRY(); -+ -+ if (num == 0) { -+ res = 0; -+ goto out; -+ } -+ -+ list_for_each_entry(thr, &cmd_threads->threads_list, thread_list_entry) { -+ n++; -+ } -+ -+ TRACE_DBG("cmd_threads %p, dev %s, tgt_dev %p, num %d, n %d", -+ cmd_threads, dev ? dev->virt_name : NULL, tgt_dev, num, n); -+ -+ if (tgt_dev != NULL) { -+ struct scst_tgt_dev *t; -+ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ if (t == tgt_dev) -+ break; -+ tgt_dev_num++; -+ } -+ } -+ -+ for (i = 0; i < num; i++) { -+ thr = kmalloc(sizeof(*thr), GFP_KERNEL); -+ if (!thr) { -+ res = -ENOMEM; -+ PRINT_ERROR("Fail to allocate thr %d", res); -+ goto out_wait; -+ } -+ -+ if (dev != NULL) { -+ thr->cmd_thread = kthread_create(scst_cmd_thread, -+ cmd_threads, "%.13s%d", dev->virt_name, n++); -+ } else if (tgt_dev != NULL) { -+ thr->cmd_thread = kthread_create(scst_cmd_thread, -+ cmd_threads, "%.10s%d_%d", -+ tgt_dev->dev->virt_name, tgt_dev_num, n++); -+ } else -+ thr->cmd_thread = kthread_create(scst_cmd_thread, -+ cmd_threads, "scstd%d", n++); -+ -+ if (IS_ERR(thr->cmd_thread)) { -+ res = PTR_ERR(thr->cmd_thread); -+ PRINT_ERROR("kthread_create() failed: %d", res); -+ kfree(thr); -+ goto out_wait; -+ } -+ -+ if (tgt_dev != NULL) { -+ int rc; -+ /* -+ * sess->acg can be NULL here, if called from -+ * scst_check_reassign_sess()! -+ */ -+ rc = set_cpus_allowed_ptr(thr->cmd_thread, -+ &tgt_dev->acg_dev->acg->acg_cpu_mask); -+ if (rc != 0) -+ PRINT_ERROR("Setting CPU affinity failed: " -+ "%d", rc); -+ } -+ -+ list_add(&thr->thread_list_entry, &cmd_threads->threads_list); -+ cmd_threads->nr_threads++; -+ -+ TRACE_DBG("Added thr %p to threads list (nr_threads %d, n %d)", -+ thr, cmd_threads->nr_threads, n); -+ -+ wake_up_process(thr->cmd_thread); -+ } -+ -+out_wait: -+ if (i > 0 && cmd_threads != &scst_main_cmd_threads) { -+ /* -+ * Wait for io_context gets initialized to avoid possible races -+ * for it from the sharing it tgt_devs. -+ */ -+ while (!*(volatile bool*)&cmd_threads->io_context_ready) { -+ TRACE_DBG("Waiting for io_context for cmd_threads %p " -+ "initialized", cmd_threads); -+ msleep(50); -+ } -+ smp_rmb(); -+ } -+ -+ if (res != 0) -+ scst_del_threads(cmd_threads, i); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* scst_mutex supposed to be held */ -+void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num) -+{ -+ struct scst_cmd_thread_t *ct, *tmp; -+ -+ TRACE_ENTRY(); -+ -+ if (num == 0) -+ goto out; -+ -+ list_for_each_entry_safe_reverse(ct, tmp, &cmd_threads->threads_list, -+ thread_list_entry) { -+ int rc; -+ struct scst_device *dev; -+ -+ rc = kthread_stop(ct->cmd_thread); -+ if (rc != 0 && rc != -EINTR) -+ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc); -+ -+ list_del(&ct->thread_list_entry); -+ -+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { -+ struct scst_tgt_dev *tgt_dev; -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ scst_del_thr_data(tgt_dev, ct->cmd_thread); -+ } -+ } -+ -+ kfree(ct); -+ -+ cmd_threads->nr_threads--; -+ -+ --num; -+ if (num == 0) -+ break; -+ } -+ -+ EXTRACHECKS_BUG_ON((cmd_threads->nr_threads == 0) && -+ (cmd_threads->io_context != NULL)); -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+ -+/* The activity supposed to be suspended and scst_mutex held */ -+void scst_stop_dev_threads(struct scst_device *dev) -+{ -+ struct scst_tgt_dev *tgt_dev; -+ -+ TRACE_ENTRY(); -+ -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ scst_tgt_dev_stop_threads(tgt_dev); -+ } -+ -+ if ((dev->threads_num > 0) && -+ (dev->threads_pool_type == SCST_THREADS_POOL_SHARED)) -+ scst_del_threads(&dev->dev_cmd_threads, -1); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* The activity supposed to be suspended and scst_mutex held */ -+int scst_create_dev_threads(struct scst_device *dev) -+{ -+ int res = 0; -+ struct scst_tgt_dev *tgt_dev; -+ -+ TRACE_ENTRY(); -+ -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ res = scst_tgt_dev_setup_threads(tgt_dev); -+ if (res != 0) -+ goto out_err; -+ } -+ -+ if ((dev->threads_num > 0) && -+ (dev->threads_pool_type == SCST_THREADS_POOL_SHARED)) { -+ res = scst_add_threads(&dev->dev_cmd_threads, dev, NULL, -+ dev->threads_num); -+ if (res != 0) -+ goto out_err; -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_err: -+ scst_stop_dev_threads(dev); -+ goto out; -+} -+ -+/* The activity supposed to be suspended and scst_mutex held */ -+int scst_assign_dev_handler(struct scst_device *dev, -+ struct scst_dev_type *handler) -+{ -+ int res = 0; -+ struct scst_tgt_dev *tgt_dev; -+ LIST_HEAD(attached_tgt_devs); -+ -+ TRACE_ENTRY(); -+ -+ BUG_ON(handler == NULL); -+ -+ if (dev->handler == handler) -+ goto out; -+ -+ if (dev->handler == NULL) -+ goto assign; -+ -+ if (dev->handler->detach_tgt) { -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ TRACE_DBG("Calling dev handler's detach_tgt(%p)", -+ tgt_dev); -+ dev->handler->detach_tgt(tgt_dev); -+ TRACE_DBG("%s", "Dev handler's detach_tgt() returned"); -+ } -+ } -+ -+ /* -+ * devt_dev sysfs must be created AFTER attach() and deleted BEFORE -+ * detach() to avoid calls from sysfs for not yet ready or already dead -+ * objects. -+ */ -+ scst_devt_dev_sysfs_del(dev); -+ -+ if (dev->handler->detach) { -+ TRACE_DBG("%s", "Calling dev handler's detach()"); -+ dev->handler->detach(dev); -+ TRACE_DBG("%s", "Old handler's detach() returned"); -+ } -+ -+ scst_stop_dev_threads(dev); -+ -+assign: -+ dev->handler = handler; -+ -+ if (handler == NULL) -+ goto out; -+ -+ dev->threads_num = handler->threads_num; -+ dev->threads_pool_type = handler->threads_pool_type; -+ -+ if (handler->attach) { -+ TRACE_DBG("Calling new dev handler's attach(%p)", dev); -+ res = handler->attach(dev); -+ TRACE_DBG("New dev handler's attach() returned %d", res); -+ if (res != 0) { -+ PRINT_ERROR("New device handler's %s attach() " -+ "failed: %d", handler->name, res); -+ goto out; -+ } -+ } -+ -+ res = scst_devt_dev_sysfs_create(dev); -+ if (res != 0) -+ goto out_detach; -+ -+ if (handler->attach_tgt) { -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ TRACE_DBG("Calling dev handler's attach_tgt(%p)", -+ tgt_dev); -+ res = handler->attach_tgt(tgt_dev); -+ TRACE_DBG("%s", "Dev handler's attach_tgt() returned"); -+ if (res != 0) { -+ PRINT_ERROR("Device handler's %s attach_tgt() " -+ "failed: %d", handler->name, res); -+ goto out_err_remove_sysfs; -+ } -+ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry, -+ &attached_tgt_devs); -+ } -+ } -+ -+ res = scst_create_dev_threads(dev); -+ if (res != 0) -+ goto out_err_detach_tgt; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_err_detach_tgt: -+ if (handler && handler->detach_tgt) { -+ list_for_each_entry(tgt_dev, &attached_tgt_devs, -+ extra_tgt_dev_list_entry) { -+ TRACE_DBG("Calling handler's detach_tgt(%p)", -+ tgt_dev); -+ handler->detach_tgt(tgt_dev); -+ TRACE_DBG("%s", "Handler's detach_tgt() returned"); -+ } -+ } -+ -+out_err_remove_sysfs: -+ scst_devt_dev_sysfs_del(dev); -+ -+out_detach: -+ if (handler && handler->detach) { -+ TRACE_DBG("%s", "Calling handler's detach()"); -+ handler->detach(dev); -+ TRACE_DBG("%s", "Handler's detach() returned"); -+ } -+ -+ dev->handler = &scst_null_devtype; -+ dev->threads_num = scst_null_devtype.threads_num; -+ dev->threads_pool_type = scst_null_devtype.threads_pool_type; -+ goto out; -+} -+ -+/** -+ * scst_init_threads() - initialize SCST processing threads pool -+ * -+ * Initializes scst_cmd_threads structure -+ */ -+void scst_init_threads(struct scst_cmd_threads *cmd_threads) -+{ -+ TRACE_ENTRY(); -+ -+ spin_lock_init(&cmd_threads->cmd_list_lock); -+ INIT_LIST_HEAD(&cmd_threads->active_cmd_list); -+ init_waitqueue_head(&cmd_threads->cmd_list_waitQ); -+ INIT_LIST_HEAD(&cmd_threads->threads_list); -+ mutex_init(&cmd_threads->io_context_mutex); -+ -+ mutex_lock(&scst_suspend_mutex); -+ list_add_tail(&cmd_threads->lists_list_entry, -+ &scst_cmd_threads_list); -+ mutex_unlock(&scst_suspend_mutex); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_init_threads); -+ -+/** -+ * scst_deinit_threads() - deinitialize SCST processing threads pool -+ * -+ * Deinitializes scst_cmd_threads structure -+ */ -+void scst_deinit_threads(struct scst_cmd_threads *cmd_threads) -+{ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_suspend_mutex); -+ list_del(&cmd_threads->lists_list_entry); -+ mutex_unlock(&scst_suspend_mutex); -+ -+ BUG_ON(cmd_threads->io_context); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_deinit_threads); -+ -+static void scst_stop_global_threads(void) -+{ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ scst_del_threads(&scst_main_cmd_threads, -1); -+ -+ if (scst_mgmt_cmd_thread) -+ kthread_stop(scst_mgmt_cmd_thread); -+ if (scst_mgmt_thread) -+ kthread_stop(scst_mgmt_thread); -+ if (scst_init_cmd_thread) -+ kthread_stop(scst_init_cmd_thread); -+ -+ mutex_unlock(&scst_mutex); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* It does NOT stop ran threads on error! */ -+static int scst_start_global_threads(int num) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ res = scst_add_threads(&scst_main_cmd_threads, NULL, NULL, num); -+ if (res < 0) -+ goto out_unlock; -+ -+ scst_init_cmd_thread = kthread_run(scst_init_thread, -+ NULL, "scst_initd"); -+ if (IS_ERR(scst_init_cmd_thread)) { -+ res = PTR_ERR(scst_init_cmd_thread); -+ PRINT_ERROR("kthread_create() for init cmd failed: %d", res); -+ scst_init_cmd_thread = NULL; -+ goto out_unlock; -+ } -+ -+ scst_mgmt_cmd_thread = kthread_run(scst_tm_thread, -+ NULL, "scsi_tm"); -+ if (IS_ERR(scst_mgmt_cmd_thread)) { -+ res = PTR_ERR(scst_mgmt_cmd_thread); -+ PRINT_ERROR("kthread_create() for TM failed: %d", res); -+ scst_mgmt_cmd_thread = NULL; -+ goto out_unlock; -+ } -+ -+ scst_mgmt_thread = kthread_run(scst_global_mgmt_thread, -+ NULL, "scst_mgmtd"); -+ if (IS_ERR(scst_mgmt_thread)) { -+ res = PTR_ERR(scst_mgmt_thread); -+ PRINT_ERROR("kthread_create() for mgmt failed: %d", res); -+ scst_mgmt_thread = NULL; -+ goto out_unlock; -+ } -+ -+out_unlock: -+ mutex_unlock(&scst_mutex); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/** -+ * scst_get_setup_id() - return SCST setup ID -+ * -+ * Returns SCST setup ID. This ID can be used for multiple -+ * setups with the same configuration. -+ */ -+unsigned int scst_get_setup_id(void) -+{ -+ return scst_setup_id; -+} -+EXPORT_SYMBOL_GPL(scst_get_setup_id); -+ -+static int scst_add(struct device *cdev, struct class_interface *intf) -+{ -+ struct scsi_device *scsidp; -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ scsidp = to_scsi_device(cdev->parent); -+ -+ if ((scsidp->host->hostt->name == NULL) || -+ (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0)) -+ res = scst_register_device(scsidp); -+ -+ TRACE_EXIT(); -+ return res; -+} -+ -+static void scst_remove(struct device *cdev, struct class_interface *intf) -+{ -+ struct scsi_device *scsidp; -+ -+ TRACE_ENTRY(); -+ -+ scsidp = to_scsi_device(cdev->parent); -+ -+ if ((scsidp->host->hostt->name == NULL) || -+ (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0)) -+ scst_unregister_device(scsidp); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static struct class_interface scst_interface = { -+ .add_dev = scst_add, -+ .remove_dev = scst_remove, -+}; -+ -+static void __init scst_print_config(void) -+{ -+ char buf[128]; -+ int i, j; -+ -+ i = snprintf(buf, sizeof(buf), "Enabled features: "); -+ j = i; -+ -+#ifdef CONFIG_SCST_STRICT_SERIALIZING -+ i += snprintf(&buf[i], sizeof(buf) - i, "STRICT_SERIALIZING"); -+#endif -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sEXTRACHECKS", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_TRACING -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sTRACING", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_DEBUG -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_DEBUG_TM -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_TM", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_DEBUG_RETRY -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_RETRY", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_DEBUG_OOM -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_OOM", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_DEBUG_SN -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_SN", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sUSE_EXPECTED_VALUES", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ -+ i += snprintf(&buf[i], sizeof(buf) - i, -+ "%sTEST_IO_IN_SIRQ", -+ (j == i) ? "" : ", "); -+#endif -+ -+#ifdef CONFIG_SCST_STRICT_SECURITY -+ i += snprintf(&buf[i], sizeof(buf) - i, "%sSTRICT_SECURITY", -+ (j == i) ? "" : ", "); -+#endif -+ -+ if (j != i) -+ PRINT_INFO("%s", buf); -+} -+ -+static int __init init_scst(void) -+{ -+ int res, i; -+ int scst_num_cpus; -+ -+ TRACE_ENTRY(); -+ -+ { -+ struct scsi_sense_hdr *shdr; -+ struct scst_order_data *o; -+ struct scst_cmd *c; -+ BUILD_BUG_ON(SCST_SENSE_BUFFERSIZE < sizeof(*shdr)); -+ BUILD_BUG_ON(sizeof(o->curr_sn) != sizeof(o->expected_sn)); -+ BUILD_BUG_ON(sizeof(c->sn) != sizeof(o->expected_sn)); -+ } -+ -+ mutex_init(&scst_mutex); -+ mutex_init(&scst_mutex2); -+ INIT_LIST_HEAD(&scst_template_list); -+ INIT_LIST_HEAD(&scst_dev_list); -+ INIT_LIST_HEAD(&scst_dev_type_list); -+ INIT_LIST_HEAD(&scst_virtual_dev_type_list); -+ spin_lock_init(&scst_main_lock); -+ spin_lock_init(&scst_init_lock); -+ init_waitqueue_head(&scst_init_cmd_list_waitQ); -+ INIT_LIST_HEAD(&scst_init_cmd_list); -+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) -+ scst_trace_flag = SCST_DEFAULT_LOG_FLAGS; -+#endif -+ spin_lock_init(&scst_mcmd_lock); -+ INIT_LIST_HEAD(&scst_active_mgmt_cmd_list); -+ INIT_LIST_HEAD(&scst_delayed_mgmt_cmd_list); -+ init_waitqueue_head(&scst_mgmt_cmd_list_waitQ); -+ init_waitqueue_head(&scst_mgmt_waitQ); -+ spin_lock_init(&scst_mgmt_lock); -+ INIT_LIST_HEAD(&scst_sess_init_list); -+ INIT_LIST_HEAD(&scst_sess_shut_list); -+ init_waitqueue_head(&scst_dev_cmd_waitQ); -+ mutex_init(&scst_suspend_mutex); -+ INIT_LIST_HEAD(&scst_cmd_threads_list); -+ cpus_setall(default_cpu_mask); -+ -+ scst_init_threads(&scst_main_cmd_threads); -+ -+ res = scst_lib_init(); -+ if (res != 0) -+ goto out_deinit_threads; -+ -+ scst_num_cpus = num_online_cpus(); -+ -+ /* ToDo: register_cpu_notifier() */ -+ -+ if (scst_threads == 0) -+ scst_threads = scst_num_cpus; -+ -+ if (scst_threads < 1) { -+ PRINT_ERROR("%s", "scst_threads can not be less than 1"); -+ scst_threads = scst_num_cpus; -+ } -+ -+#define INIT_CACHEP(p, s, o) do { \ -+ p = KMEM_CACHE(s, SCST_SLAB_FLAGS); \ -+ TRACE_MEM("Slab create: %s at %p size %zd", #s, p, \ -+ sizeof(struct s)); \ -+ if (p == NULL) { \ -+ res = -ENOMEM; \ -+ goto o; \ -+ } \ -+ } while (0) -+ -+ INIT_CACHEP(scst_mgmt_cachep, scst_mgmt_cmd, out_lib_exit); -+ INIT_CACHEP(scst_mgmt_stub_cachep, scst_mgmt_cmd_stub, -+ out_destroy_mgmt_cache); -+ INIT_CACHEP(scst_ua_cachep, scst_tgt_dev_UA, -+ out_destroy_mgmt_stub_cache); -+ { -+ struct scst_sense { uint8_t s[SCST_SENSE_BUFFERSIZE]; }; -+ INIT_CACHEP(scst_sense_cachep, scst_sense, -+ out_destroy_ua_cache); -+ } -+ INIT_CACHEP(scst_aen_cachep, scst_aen, out_destroy_sense_cache); -+ INIT_CACHEP(scst_cmd_cachep, scst_cmd, out_destroy_aen_cache); -+ INIT_CACHEP(scst_sess_cachep, scst_session, out_destroy_cmd_cache); -+ INIT_CACHEP(scst_tgtd_cachep, scst_tgt_dev, out_destroy_sess_cache); -+ INIT_CACHEP(scst_acgd_cachep, scst_acg_dev, out_destroy_tgt_cache); -+ -+ scst_mgmt_mempool = mempool_create(64, mempool_alloc_slab, -+ mempool_free_slab, scst_mgmt_cachep); -+ if (scst_mgmt_mempool == NULL) { -+ res = -ENOMEM; -+ goto out_destroy_acg_cache; -+ } -+ -+ /* -+ * All mgmt stubs, UAs and sense buffers are bursty and loosing them -+ * may have fatal consequences, so let's have big pools for them. -+ */ -+ -+ scst_mgmt_stub_mempool = mempool_create(1024, mempool_alloc_slab, -+ mempool_free_slab, scst_mgmt_stub_cachep); -+ if (scst_mgmt_stub_mempool == NULL) { -+ res = -ENOMEM; -+ goto out_destroy_mgmt_mempool; -+ } -+ -+ scst_ua_mempool = mempool_create(512, mempool_alloc_slab, -+ mempool_free_slab, scst_ua_cachep); -+ if (scst_ua_mempool == NULL) { -+ res = -ENOMEM; -+ goto out_destroy_mgmt_stub_mempool; -+ } -+ -+ scst_sense_mempool = mempool_create(1024, mempool_alloc_slab, -+ mempool_free_slab, scst_sense_cachep); -+ if (scst_sense_mempool == NULL) { -+ res = -ENOMEM; -+ goto out_destroy_ua_mempool; -+ } -+ -+ scst_aen_mempool = mempool_create(100, mempool_alloc_slab, -+ mempool_free_slab, scst_aen_cachep); -+ if (scst_aen_mempool == NULL) { -+ res = -ENOMEM; -+ goto out_destroy_sense_mempool; -+ } -+ -+ res = scst_sysfs_init(); -+ if (res != 0) -+ goto out_destroy_aen_mempool; -+ -+ scst_tg_init(); -+ -+ if (scst_max_cmd_mem == 0) { -+ struct sysinfo si; -+ si_meminfo(&si); -+#if BITS_PER_LONG == 32 -+ scst_max_cmd_mem = min( -+ (((uint64_t)(si.totalram - si.totalhigh) << PAGE_SHIFT) -+ >> 20) >> 2, (uint64_t)1 << 30); -+#else -+ scst_max_cmd_mem = (((si.totalram - si.totalhigh) << PAGE_SHIFT) -+ >> 20) >> 2; -+#endif -+ } -+ -+ if (scst_max_dev_cmd_mem != 0) { -+ if (scst_max_dev_cmd_mem > scst_max_cmd_mem) { -+ PRINT_ERROR("scst_max_dev_cmd_mem (%d) > " -+ "scst_max_cmd_mem (%d)", -+ scst_max_dev_cmd_mem, -+ scst_max_cmd_mem); -+ scst_max_dev_cmd_mem = scst_max_cmd_mem; -+ } -+ } else -+ scst_max_dev_cmd_mem = scst_max_cmd_mem * 2 / 5; -+ -+ res = scst_sgv_pools_init( -+ ((uint64_t)scst_max_cmd_mem << 10) >> (PAGE_SHIFT - 10), 0); -+ if (res != 0) -+ goto out_sysfs_cleanup; -+ -+ res = scsi_register_interface(&scst_interface); -+ if (res != 0) -+ goto out_destroy_sgv_pool; -+ -+ for (i = 0; i < (int)ARRAY_SIZE(scst_percpu_infos); i++) { -+ atomic_set(&scst_percpu_infos[i].cpu_cmd_count, 0); -+ spin_lock_init(&scst_percpu_infos[i].tasklet_lock); -+ INIT_LIST_HEAD(&scst_percpu_infos[i].tasklet_cmd_list); -+ tasklet_init(&scst_percpu_infos[i].tasklet, -+ (void *)scst_cmd_tasklet, -+ (unsigned long)&scst_percpu_infos[i]); -+ } -+ -+ TRACE_DBG("%d CPUs found, starting %d threads", scst_num_cpus, -+ scst_threads); -+ -+ res = scst_start_global_threads(scst_threads); -+ if (res < 0) -+ goto out_thread_free; -+ -+ PRINT_INFO("SCST version %s loaded successfully (max mem for " -+ "commands %dMB, per device %dMB)", SCST_VERSION_STRING, -+ scst_max_cmd_mem, scst_max_dev_cmd_mem); -+ -+ scst_print_config(); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_thread_free: -+ scst_stop_global_threads(); -+ -+ scsi_unregister_interface(&scst_interface); -+ -+out_destroy_sgv_pool: -+ scst_sgv_pools_deinit(); -+ scst_tg_cleanup(); -+ -+out_sysfs_cleanup: -+ scst_sysfs_cleanup(); -+ -+out_destroy_aen_mempool: -+ mempool_destroy(scst_aen_mempool); -+ -+out_destroy_sense_mempool: -+ mempool_destroy(scst_sense_mempool); -+ -+out_destroy_ua_mempool: -+ mempool_destroy(scst_ua_mempool); -+ -+out_destroy_mgmt_stub_mempool: -+ mempool_destroy(scst_mgmt_stub_mempool); -+ -+out_destroy_mgmt_mempool: -+ mempool_destroy(scst_mgmt_mempool); -+ -+out_destroy_acg_cache: -+ kmem_cache_destroy(scst_acgd_cachep); -+ -+out_destroy_tgt_cache: -+ kmem_cache_destroy(scst_tgtd_cachep); -+ -+out_destroy_sess_cache: -+ kmem_cache_destroy(scst_sess_cachep); -+ -+out_destroy_cmd_cache: -+ kmem_cache_destroy(scst_cmd_cachep); -+ -+out_destroy_aen_cache: -+ kmem_cache_destroy(scst_aen_cachep); -+ -+out_destroy_sense_cache: -+ kmem_cache_destroy(scst_sense_cachep); -+ -+out_destroy_ua_cache: -+ kmem_cache_destroy(scst_ua_cachep); -+ -+out_destroy_mgmt_stub_cache: -+ kmem_cache_destroy(scst_mgmt_stub_cachep); -+ -+out_destroy_mgmt_cache: -+ kmem_cache_destroy(scst_mgmt_cachep); -+ -+out_lib_exit: -+ scst_lib_exit(); -+ -+out_deinit_threads: -+ scst_deinit_threads(&scst_main_cmd_threads); -+ goto out; -+} -+ -+static void __exit exit_scst(void) -+{ -+ TRACE_ENTRY(); -+ -+ /* ToDo: unregister_cpu_notifier() */ -+ -+ scst_stop_global_threads(); -+ -+ scst_deinit_threads(&scst_main_cmd_threads); -+ -+ scsi_unregister_interface(&scst_interface); -+ -+ scst_sgv_pools_deinit(); -+ -+ scst_tg_cleanup(); -+ -+ scst_sysfs_cleanup(); -+ -+#define DEINIT_CACHEP(p) do { \ -+ kmem_cache_destroy(p); \ -+ p = NULL; \ -+ } while (0) -+ -+ mempool_destroy(scst_mgmt_mempool); -+ mempool_destroy(scst_mgmt_stub_mempool); -+ mempool_destroy(scst_ua_mempool); -+ mempool_destroy(scst_sense_mempool); -+ mempool_destroy(scst_aen_mempool); -+ -+ DEINIT_CACHEP(scst_mgmt_cachep); -+ DEINIT_CACHEP(scst_mgmt_stub_cachep); -+ DEINIT_CACHEP(scst_ua_cachep); -+ DEINIT_CACHEP(scst_sense_cachep); -+ DEINIT_CACHEP(scst_aen_cachep); -+ DEINIT_CACHEP(scst_cmd_cachep); -+ DEINIT_CACHEP(scst_sess_cachep); -+ DEINIT_CACHEP(scst_tgtd_cachep); -+ DEINIT_CACHEP(scst_acgd_cachep); -+ -+ scst_lib_exit(); -+ -+ PRINT_INFO("%s", "SCST unloaded"); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+module_init(init_scst); -+module_exit(exit_scst); -+ -+MODULE_AUTHOR("Vladislav Bolkhovitin"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("SCSI target core"); -+MODULE_VERSION(SCST_VERSION_STRING); -diff -uprN orig/linux-3.2/drivers/scst/scst_module.c linux-3.2/drivers/scst/scst_module.c ---- orig/linux-3.2/drivers/scst/scst_module.c -+++ linux-3.2/drivers/scst/scst_module.c -@@ -0,0 +1,70 @@ -+/* -+ * scst_module.c -+ * -+ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net> -+ * Copyright (C) 2004 - 2005 Leonid Stoljar -+ * Copyright (C) 2007 - 2010 ID7 Ltd. -+ * Copyright (C) 2010 - 2011 SCST Ltd. -+ * -+ * Support for loading target modules. The usage is similar to scsi_module.c -+ * -+ * 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, version 2 -+ * of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+ -+#include <scst.h> -+ -+static int __init init_this_scst_driver(void) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ res = scst_register_target_template(&driver_target_template); -+ TRACE_DBG("scst_register_target_template() returned %d", res); -+ if (res < 0) -+ goto out; -+ -+#ifdef SCST_REGISTER_INITIATOR_DRIVER -+ driver_template.module = THIS_MODULE; -+ scsi_register_module(MODULE_SCSI_HA, &driver_template); -+ TRACE_DBG("driver_template.present=%d", -+ driver_template.present); -+ if (driver_template.present == 0) { -+ res = -ENODEV; -+ MOD_DEC_USE_COUNT; -+ goto out; -+ } -+#endif -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static void __exit exit_this_scst_driver(void) -+{ -+ TRACE_ENTRY(); -+ -+#ifdef SCST_REGISTER_INITIATOR_DRIVER -+ scsi_unregister_module(MODULE_SCSI_HA, &driver_template); -+#endif -+ -+ scst_unregister_target_template(&driver_target_template); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+module_init(init_this_scst_driver); -+module_exit(exit_this_scst_driver); -diff -uprN orig/linux-3.2/drivers/scst/scst_priv.h linux-3.2/drivers/scst/scst_priv.h ---- orig/linux-3.2/drivers/scst/scst_priv.h -+++ linux-3.2/drivers/scst/scst_priv.h -@@ -0,0 +1,646 @@ -+/* -+ * scst_priv.h -+ * -+ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net> -+ * Copyright (C) 2004 - 2005 Leonid Stoljar -+ * Copyright (C) 2007 - 2010 ID7 Ltd. -+ * Copyright (C) 2010 - 2011 SCST Ltd. -+ * -+ * 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, version 2 -+ * of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __SCST_PRIV_H -+#define __SCST_PRIV_H -+ -+#include <linux/types.h> -+#include <linux/slab.h> -+#include <linux/export.h> -+#include <scsi/scsi.h> -+#include <scsi/scsi_cmnd.h> -+#include <scsi/scsi_driver.h> -+#include <scsi/scsi_device.h> -+#include <scsi/scsi_host.h> -+ -+#define LOG_PREFIX "scst" -+ -+#include <scst/scst_debug.h> -+ -+#define TRACE_RTRY 0x80000000 -+#define TRACE_SCSI_SERIALIZING 0x40000000 -+/** top being the edge away from the interrupt */ -+#define TRACE_SND_TOP 0x20000000 -+#define TRACE_RCV_TOP 0x01000000 -+/** bottom being the edge toward the interrupt */ -+#define TRACE_SND_BOT 0x08000000 -+#define TRACE_RCV_BOT 0x04000000 -+ -+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) -+#define trace_flag scst_trace_flag -+extern unsigned long scst_trace_flag; -+#endif -+ -+#ifdef CONFIG_SCST_DEBUG -+ -+#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_PID | \ -+ TRACE_LINE | TRACE_FUNCTION | TRACE_SPECIAL | TRACE_MGMT | \ -+ TRACE_MGMT_DEBUG | TRACE_RTRY) -+ -+#define TRACE_RETRY(args...) TRACE_DBG_FLAG(TRACE_RTRY, args) -+#define TRACE_SN(args...) TRACE_DBG_FLAG(TRACE_SCSI_SERIALIZING, args) -+#define TRACE_SEND_TOP(args...) TRACE_DBG_FLAG(TRACE_SND_TOP, args) -+#define TRACE_RECV_TOP(args...) TRACE_DBG_FLAG(TRACE_RCV_TOP, args) -+#define TRACE_SEND_BOT(args...) TRACE_DBG_FLAG(TRACE_SND_BOT, args) -+#define TRACE_RECV_BOT(args...) TRACE_DBG_FLAG(TRACE_RCV_BOT, args) -+ -+#else /* CONFIG_SCST_DEBUG */ -+ -+# ifdef CONFIG_SCST_TRACING -+#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \ -+ TRACE_SPECIAL) -+# else -+#define SCST_DEFAULT_LOG_FLAGS 0 -+# endif -+ -+#define TRACE_RETRY(args...) -+#define TRACE_SN(args...) -+#define TRACE_SEND_TOP(args...) -+#define TRACE_RECV_TOP(args...) -+#define TRACE_SEND_BOT(args...) -+#define TRACE_RECV_BOT(args...) -+ -+#endif -+ -+/** -+ ** Bits for scst_flags -+ **/ -+ -+/* -+ * Set if new commands initialization is being suspended for a while. -+ * Used to let TM commands execute while preparing the suspend, since -+ * RESET or ABORT could be necessary to free SCSI commands. -+ */ -+#define SCST_FLAG_SUSPENDING 0 -+ -+/* Set if new commands initialization is suspended for a while */ -+#define SCST_FLAG_SUSPENDED 1 -+ -+/** -+ ** Return codes for cmd state process functions. Codes are the same as -+ ** for SCST_EXEC_* to avoid translation to them and, hence, have better code. -+ **/ -+#define SCST_CMD_STATE_RES_CONT_NEXT SCST_EXEC_COMPLETED -+#define SCST_CMD_STATE_RES_CONT_SAME SCST_EXEC_NOT_COMPLETED -+#define SCST_CMD_STATE_RES_NEED_THREAD (SCST_EXEC_NOT_COMPLETED+1) -+ -+/** -+ ** Maximum count of uncompleted commands that an initiator could -+ ** queue on any device. Then it will start getting TASK QUEUE FULL status. -+ **/ -+#define SCST_MAX_TGT_DEV_COMMANDS 48 -+ -+/** -+ ** Maximum count of uncompleted commands that could be queued on any device. -+ ** Then initiators sending commands to this device will start getting -+ ** TASK QUEUE FULL status. -+ **/ -+#define SCST_MAX_DEV_COMMANDS 256 -+ -+#define SCST_TGT_RETRY_TIMEOUT (3/2*HZ) -+ -+/* Activities suspending timeout */ -+#define SCST_SUSPENDING_TIMEOUT (90 * HZ) -+ -+extern struct mutex scst_mutex2; -+ -+extern int scst_threads; -+ -+extern unsigned int scst_max_dev_cmd_mem; -+ -+extern mempool_t *scst_mgmt_mempool; -+extern mempool_t *scst_mgmt_stub_mempool; -+extern mempool_t *scst_ua_mempool; -+extern mempool_t *scst_sense_mempool; -+extern mempool_t *scst_aen_mempool; -+ -+extern struct kmem_cache *scst_cmd_cachep; -+extern struct kmem_cache *scst_sess_cachep; -+extern struct kmem_cache *scst_tgtd_cachep; -+extern struct kmem_cache *scst_acgd_cachep; -+ -+extern spinlock_t scst_main_lock; -+ -+extern unsigned long scst_flags; -+extern struct list_head scst_template_list; -+extern struct list_head scst_dev_list; -+extern struct list_head scst_dev_type_list; -+extern struct list_head scst_virtual_dev_type_list; -+extern wait_queue_head_t scst_dev_cmd_waitQ; -+ -+extern unsigned int scst_setup_id; -+ -+#define SCST_DEF_MAX_TASKLET_CMD 10 -+extern int scst_max_tasklet_cmd; -+ -+extern spinlock_t scst_init_lock; -+extern struct list_head scst_init_cmd_list; -+extern wait_queue_head_t scst_init_cmd_list_waitQ; -+extern unsigned int scst_init_poll_cnt; -+ -+extern struct scst_cmd_threads scst_main_cmd_threads; -+ -+extern spinlock_t scst_mcmd_lock; -+/* The following lists protected by scst_mcmd_lock */ -+extern struct list_head scst_active_mgmt_cmd_list; -+extern struct list_head scst_delayed_mgmt_cmd_list; -+extern wait_queue_head_t scst_mgmt_cmd_list_waitQ; -+ -+struct scst_percpu_info { -+ atomic_t cpu_cmd_count; -+ spinlock_t tasklet_lock; -+ struct list_head tasklet_cmd_list; -+ struct tasklet_struct tasklet; -+} ____cacheline_aligned_in_smp; -+extern struct scst_percpu_info scst_percpu_infos[NR_CPUS]; -+ -+extern wait_queue_head_t scst_mgmt_waitQ; -+extern spinlock_t scst_mgmt_lock; -+extern struct list_head scst_sess_init_list; -+extern struct list_head scst_sess_shut_list; -+ -+extern cpumask_t default_cpu_mask; -+ -+struct scst_cmd_thread_t { -+ struct task_struct *cmd_thread; -+ struct list_head thread_list_entry; -+}; -+ -+static inline bool scst_set_io_context(struct scst_cmd *cmd, -+ struct io_context **old) -+{ -+ bool res; -+ -+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ -+ return false; -+#endif -+ -+ if (cmd->cmd_threads == &scst_main_cmd_threads) { -+ EXTRACHECKS_BUG_ON(in_interrupt()); -+ /* -+ * No need for any ref counting action, because io_context -+ * supposed to be cleared in the end of the caller function. -+ */ -+ current->io_context = cmd->tgt_dev->async_io_context; -+ res = true; -+ TRACE_DBG("io_context %p (tgt_dev %p)", current->io_context, -+ cmd->tgt_dev); -+ EXTRACHECKS_BUG_ON(current->io_context == NULL); -+ } else -+ res = false; -+ -+ return res; -+} -+ -+static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev, -+ struct io_context *old) -+{ -+ current->io_context = old; -+ TRACE_DBG("io_context %p reset", current->io_context); -+ return; -+} -+ -+/* -+ * Converts string presentation of threads pool type to enum. -+ * Returns SCST_THREADS_POOL_TYPE_INVALID if the string is invalid. -+ */ -+extern enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type( -+ const char *p, int len); -+ -+extern int scst_add_threads(struct scst_cmd_threads *cmd_threads, -+ struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num); -+extern void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num); -+ -+extern int scst_create_dev_threads(struct scst_device *dev); -+extern void scst_stop_dev_threads(struct scst_device *dev); -+ -+extern int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev); -+extern void scst_tgt_dev_stop_threads(struct scst_tgt_dev *tgt_dev); -+ -+extern bool scst_del_thr_data(struct scst_tgt_dev *tgt_dev, -+ struct task_struct *tsk); -+ -+extern struct scst_dev_type scst_null_devtype; -+ -+extern struct scst_cmd *__scst_check_deferred_commands( -+ struct scst_order_data *order_data); -+ -+/* Used to save the function call on the fast path */ -+static inline struct scst_cmd *scst_check_deferred_commands( -+ struct scst_order_data *order_data) -+{ -+ if (order_data->def_cmd_count == 0) -+ return NULL; -+ else -+ return __scst_check_deferred_commands(order_data); -+} -+ -+static inline void scst_make_deferred_commands_active( -+ struct scst_order_data *order_data) -+{ -+ struct scst_cmd *c; -+ -+ c = __scst_check_deferred_commands(order_data); -+ if (c != NULL) { -+ TRACE_SN("Adding cmd %p to active cmd list", c); -+ spin_lock_irq(&c->cmd_threads->cmd_list_lock); -+ list_add_tail(&c->cmd_list_entry, -+ &c->cmd_threads->active_cmd_list); -+ wake_up(&c->cmd_threads->cmd_list_waitQ); -+ spin_unlock_irq(&c->cmd_threads->cmd_list_lock); -+ } -+ -+ return; -+} -+ -+void scst_inc_expected_sn(struct scst_order_data *order_data, atomic_t *slot); -+int scst_check_hq_cmd(struct scst_cmd *cmd); -+ -+void scst_unblock_deferred(struct scst_order_data *order_data, -+ struct scst_cmd *cmd_sn); -+ -+void scst_on_hq_cmd_response(struct scst_cmd *cmd); -+void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd); -+ -+int scst_pre_parse(struct scst_cmd *cmd); -+ -+int scst_cmd_thread(void *arg); -+void scst_cmd_tasklet(long p); -+int scst_init_thread(void *arg); -+int scst_tm_thread(void *arg); -+int scst_global_mgmt_thread(void *arg); -+ -+void scst_zero_write_rest(struct scst_cmd *cmd); -+void scst_limit_sg_write_len(struct scst_cmd *cmd); -+void scst_adjust_resp_data_len(struct scst_cmd *cmd); -+ -+int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds); -+ -+int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt); -+void scst_free_tgt(struct scst_tgt *tgt); -+ -+int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev); -+void scst_free_device(struct scst_device *dev); -+ -+struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt, -+ const char *acg_name, bool tgt_acg); -+void scst_del_free_acg(struct scst_acg *acg); -+ -+struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name); -+struct scst_acg *scst_find_acg(const struct scst_session *sess); -+ -+void scst_check_reassign_sessions(void); -+ -+int scst_sess_alloc_tgt_devs(struct scst_session *sess); -+void scst_sess_free_tgt_devs(struct scst_session *sess); -+void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA); -+ -+int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, -+ struct scst_device *dev, uint64_t lun, int read_only, -+ bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev); -+int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun, -+ bool gen_scst_report_luns_changed); -+ -+int scst_acg_add_acn(struct scst_acg *acg, const char *name); -+void scst_del_free_acn(struct scst_acn *acn, bool reassign); -+struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name); -+ -+/* The activity supposed to be suspended and scst_mutex held */ -+static inline bool scst_acg_sess_is_empty(struct scst_acg *acg) -+{ -+ return list_empty(&acg->acg_sess_list); -+} -+ -+int scst_prepare_request_sense(struct scst_cmd *orig_cmd); -+int scst_finish_internal_cmd(struct scst_cmd *cmd); -+ -+void scst_store_sense(struct scst_cmd *cmd); -+ -+int scst_assign_dev_handler(struct scst_device *dev, -+ struct scst_dev_type *handler); -+ -+struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask, -+ const char *initiator_name); -+void scst_free_session(struct scst_session *sess); -+void scst_free_session_callback(struct scst_session *sess); -+ -+struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb, -+ unsigned int cdb_len, gfp_t gfp_mask); -+void scst_free_cmd(struct scst_cmd *cmd); -+static inline void scst_destroy_cmd(struct scst_cmd *cmd) -+{ -+ kmem_cache_free(scst_cmd_cachep, cmd); -+ return; -+} -+ -+void scst_check_retries(struct scst_tgt *tgt); -+ -+int scst_alloc_space(struct scst_cmd *cmd); -+ -+int scst_lib_init(void); -+void scst_lib_exit(void); -+ -+__be64 scst_pack_lun(const uint64_t lun, enum scst_lun_addr_method addr_method); -+uint64_t scst_unpack_lun(const uint8_t *lun, int len); -+ -+struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask); -+void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd); -+void scst_done_cmd_mgmt(struct scst_cmd *cmd); -+ -+static inline void scst_devt_cleanup(struct scst_dev_type *devt) { } -+ -+void scst_tg_init(void); -+void scst_tg_cleanup(void); -+int scst_dg_add(struct kobject *parent, const char *name); -+int scst_dg_remove(const char *name); -+struct scst_dev_group *scst_lookup_dg_by_kobj(struct kobject *kobj); -+int scst_dg_dev_add(struct scst_dev_group *dg, const char *name); -+int scst_dg_dev_remove_by_name(struct scst_dev_group *dg, const char *name); -+int scst_dg_dev_remove_by_dev(struct scst_device *dev); -+int scst_tg_add(struct scst_dev_group *dg, const char *name); -+int scst_tg_remove_by_name(struct scst_dev_group *dg, const char *name); -+int scst_tg_set_state(struct scst_target_group *tg, enum scst_tg_state state); -+int scst_tg_tgt_add(struct scst_target_group *tg, const char *name); -+int scst_tg_tgt_remove_by_name(struct scst_target_group *tg, const char *name); -+void scst_tg_tgt_remove_by_tgt(struct scst_tgt *tgt); -+int scst_dg_sysfs_add(struct kobject *parent, struct scst_dev_group *dg); -+void scst_dg_sysfs_del(struct scst_dev_group *dg); -+int scst_dg_dev_sysfs_add(struct scst_dev_group *dg, struct scst_dg_dev *dgdev); -+void scst_dg_dev_sysfs_del(struct scst_dev_group *dg, -+ struct scst_dg_dev *dgdev); -+int scst_tg_sysfs_add(struct scst_dev_group *dg, -+ struct scst_target_group *tg); -+void scst_tg_sysfs_del(struct scst_target_group *tg); -+int scst_tg_tgt_sysfs_add(struct scst_target_group *tg, -+ struct scst_tg_tgt *tg_tgt); -+void scst_tg_tgt_sysfs_del(struct scst_target_group *tg, -+ struct scst_tg_tgt *tg_tgt); -+ -+extern const struct sysfs_ops scst_sysfs_ops; -+int scst_sysfs_init(void); -+void scst_sysfs_cleanup(void); -+int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt); -+void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt); -+int scst_tgt_sysfs_create(struct scst_tgt *tgt); -+void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt); -+void scst_tgt_sysfs_del(struct scst_tgt *tgt); -+int scst_sess_sysfs_create(struct scst_session *sess); -+void scst_sess_sysfs_del(struct scst_session *sess); -+int scst_recreate_sess_luns_link(struct scst_session *sess); -+int scst_add_sgv_kobj(struct kobject *parent, const char *name); -+void scst_del_put_sgv_kobj(void); -+int scst_devt_sysfs_create(struct scst_dev_type *devt); -+void scst_devt_sysfs_del(struct scst_dev_type *devt); -+int scst_dev_sysfs_create(struct scst_device *dev); -+void scst_dev_sysfs_del(struct scst_device *dev); -+int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev); -+void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev); -+int scst_devt_dev_sysfs_create(struct scst_device *dev); -+void scst_devt_dev_sysfs_del(struct scst_device *dev); -+int scst_acg_sysfs_create(struct scst_tgt *tgt, -+ struct scst_acg *acg); -+void scst_acg_sysfs_del(struct scst_acg *acg); -+int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev, -+ struct kobject *parent); -+void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev); -+int scst_acn_sysfs_create(struct scst_acn *acn); -+void scst_acn_sysfs_del(struct scst_acn *acn); -+ -+void __scst_dev_check_set_UA(struct scst_device *dev, struct scst_cmd *exclude, -+ const uint8_t *sense, int sense_len); -+void scst_tgt_dev_del_free_UA(struct scst_tgt_dev *tgt_dev, -+ struct scst_tgt_dev_UA *ua); -+static inline void scst_dev_check_set_UA(struct scst_device *dev, -+ struct scst_cmd *exclude, const uint8_t *sense, int sense_len) -+{ -+ spin_lock_bh(&dev->dev_lock); -+ __scst_dev_check_set_UA(dev, exclude, sense, sense_len); -+ spin_unlock_bh(&dev->dev_lock); -+ return; -+} -+void scst_dev_check_set_local_UA(struct scst_device *dev, -+ struct scst_cmd *exclude, const uint8_t *sense, int sense_len); -+ -+#define SCST_SET_UA_FLAG_AT_HEAD 1 -+#define SCST_SET_UA_FLAG_GLOBAL 2 -+ -+void scst_check_set_UA(struct scst_tgt_dev *tgt_dev, -+ const uint8_t *sense, int sense_len, int flags); -+int scst_set_pending_UA(struct scst_cmd *cmd); -+ -+void scst_report_luns_changed(struct scst_acg *acg); -+ -+void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, -+ bool other_ini, bool call_dev_task_mgmt_fn); -+void scst_process_reset(struct scst_device *dev, -+ struct scst_session *originator, struct scst_cmd *exclude_cmd, -+ struct scst_mgmt_cmd *mcmd, bool setUA); -+ -+bool scst_is_ua_global(const uint8_t *sense, int len); -+void scst_requeue_ua(struct scst_cmd *cmd); -+ -+struct scst_aen *scst_alloc_aen(struct scst_session *sess, -+ uint64_t unpacked_lun); -+void scst_free_aen(struct scst_aen *aen); -+ -+void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev, -+ int key, int asc, int ascq); -+ -+static inline bool scst_is_implicit_hq_cmd(struct scst_cmd *cmd) -+{ -+ return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0; -+} -+ -+static inline bool scst_is_serialized_cmd(struct scst_cmd *cmd) -+{ -+ return (cmd->op_flags & SCST_SERIALIZED) != 0; -+} -+ -+static inline bool scst_is_strictly_serialized_cmd(struct scst_cmd *cmd) -+{ -+ return (cmd->op_flags & SCST_STRICTLY_SERIALIZED) == SCST_STRICTLY_SERIALIZED; -+} -+ -+/* -+ * Some notes on devices "blocking". Blocking means that no -+ * commands will go from SCST to underlying SCSI device until it -+ * is unblocked. But, except for strictly serialized commands, -+ * we don't care about all commands that already on the device. -+ */ -+ -+extern void scst_block_dev(struct scst_device *dev); -+extern void scst_unblock_dev(struct scst_device *dev); -+ -+bool __scst_check_blocked_dev(struct scst_cmd *cmd); -+ -+/* -+ * Increases global SCST ref counters which prevent from entering into suspended -+ * activities stage, so protects from any global management operations. -+ */ -+static inline atomic_t *scst_get(void) -+{ -+ atomic_t *a; -+ /* -+ * We don't mind if we because of preemption inc counter from another -+ * CPU as soon in the majority cases we will the correct one. So, let's -+ * have preempt_disable/enable only in the debug build to avoid warning. -+ */ -+#ifdef CONFIG_DEBUG_PREEMPT -+ preempt_disable(); -+#endif -+ a = &scst_percpu_infos[smp_processor_id()].cpu_cmd_count; -+ atomic_inc(a); -+#ifdef CONFIG_DEBUG_PREEMPT -+ preempt_enable(); -+#endif -+ TRACE_DBG("Incrementing cpu_cmd_count %p (new value %d)", -+ a, atomic_read(a)); -+ /* See comment about smp_mb() in scst_suspend_activity() */ -+ smp_mb__after_atomic_inc(); -+ -+ return a; -+} -+ -+/* -+ * Decreases global SCST ref counters which prevent from entering into suspended -+ * activities stage, so protects from any global management operations. On -+ * all them zero, if suspending activities is waiting, it will be proceed. -+ */ -+static inline void scst_put(atomic_t *a) -+{ -+ int f; -+ f = atomic_dec_and_test(a); -+ /* See comment about smp_mb() in scst_suspend_activity() */ -+ if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) && f) { -+ TRACE_MGMT_DBG("%s", "Waking up scst_dev_cmd_waitQ"); -+ wake_up_all(&scst_dev_cmd_waitQ); -+ } -+ TRACE_DBG("Decrementing cpu_cmd_count %p (new value %d)", -+ a, atomic_read(a)); -+} -+ -+int scst_get_cmd_counter(void); -+ -+void scst_sched_session_free(struct scst_session *sess); -+ -+static inline void scst_sess_get(struct scst_session *sess) -+{ -+ atomic_inc(&sess->refcnt); -+ TRACE_DBG("Incrementing sess %p refcnt (new value %d)", -+ sess, atomic_read(&sess->refcnt)); -+} -+ -+static inline void scst_sess_put(struct scst_session *sess) -+{ -+ TRACE_DBG("Decrementing sess %p refcnt (new value %d)", -+ sess, atomic_read(&sess->refcnt)-1); -+ if (atomic_dec_and_test(&sess->refcnt)) -+ scst_sched_session_free(sess); -+} -+ -+static inline void __scst_cmd_get(struct scst_cmd *cmd) -+{ -+ atomic_inc(&cmd->cmd_ref); -+ TRACE_DBG("Incrementing cmd %p ref (new value %d)", -+ cmd, atomic_read(&cmd->cmd_ref)); -+} -+ -+static inline void __scst_cmd_put(struct scst_cmd *cmd) -+{ -+ TRACE_DBG("Decrementing cmd %p ref (new value %d)", -+ cmd, atomic_read(&cmd->cmd_ref)-1); -+ if (atomic_dec_and_test(&cmd->cmd_ref)) -+ scst_free_cmd(cmd); -+} -+ -+extern void scst_throttle_cmd(struct scst_cmd *cmd); -+extern void scst_unthrottle_cmd(struct scst_cmd *cmd); -+ -+#ifdef CONFIG_SCST_DEBUG_TM -+extern void tm_dbg_check_released_cmds(void); -+extern int tm_dbg_check_cmd(struct scst_cmd *cmd); -+extern void tm_dbg_release_cmd(struct scst_cmd *cmd); -+extern void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, -+ int force); -+extern int tm_dbg_is_release(void); -+#else -+static inline void tm_dbg_check_released_cmds(void) {} -+static inline int tm_dbg_check_cmd(struct scst_cmd *cmd) -+{ -+ return 0; -+} -+static inline void tm_dbg_release_cmd(struct scst_cmd *cmd) {} -+static inline void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, -+ int force) {} -+static inline int tm_dbg_is_release(void) -+{ -+ return 0; -+} -+#endif /* CONFIG_SCST_DEBUG_TM */ -+ -+#ifdef CONFIG_SCST_DEBUG_SN -+void scst_check_debug_sn(struct scst_cmd *cmd); -+#else -+static inline void scst_check_debug_sn(struct scst_cmd *cmd) {} -+#endif -+ -+static inline int scst_sn_before(uint32_t seq1, uint32_t seq2) -+{ -+ return (int32_t)(seq1-seq2) < 0; -+} -+ -+int gen_relative_target_port_id(uint16_t *id); -+bool scst_is_relative_target_port_id_unique(uint16_t id, -+ const struct scst_tgt *t); -+ -+#ifdef CONFIG_SCST_MEASURE_LATENCY -+ -+void scst_set_start_time(struct scst_cmd *cmd); -+void scst_set_cur_start(struct scst_cmd *cmd); -+void scst_set_parse_time(struct scst_cmd *cmd); -+void scst_set_alloc_buf_time(struct scst_cmd *cmd); -+void scst_set_restart_waiting_time(struct scst_cmd *cmd); -+void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd); -+void scst_set_pre_exec_time(struct scst_cmd *cmd); -+void scst_set_exec_time(struct scst_cmd *cmd); -+void scst_set_dev_done_time(struct scst_cmd *cmd); -+void scst_set_xmit_time(struct scst_cmd *cmd); -+void scst_set_tgt_on_free_time(struct scst_cmd *cmd); -+void scst_set_dev_on_free_time(struct scst_cmd *cmd); -+void scst_update_lat_stats(struct scst_cmd *cmd); -+ -+#else -+ -+static inline void scst_set_start_time(struct scst_cmd *cmd) {} -+static inline void scst_set_cur_start(struct scst_cmd *cmd) {} -+static inline void scst_set_parse_time(struct scst_cmd *cmd) {} -+static inline void scst_set_alloc_buf_time(struct scst_cmd *cmd) {} -+static inline void scst_set_restart_waiting_time(struct scst_cmd *cmd) {} -+static inline void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd) {} -+static inline void scst_set_pre_exec_time(struct scst_cmd *cmd) {} -+static inline void scst_set_exec_time(struct scst_cmd *cmd) {} -+static inline void scst_set_dev_done_time(struct scst_cmd *cmd) {} -+static inline void scst_set_xmit_time(struct scst_cmd *cmd) {} -+static inline void scst_set_tgt_on_free_time(struct scst_cmd *cmd) {} -+static inline void scst_set_dev_on_free_time(struct scst_cmd *cmd) {} -+static inline void scst_update_lat_stats(struct scst_cmd *cmd) {} -+ -+#endif /* CONFIG_SCST_MEASURE_LATENCY */ -+ -+#endif /* __SCST_PRIV_H */ -diff -uprN orig/linux-3.2/drivers/scst/scst_targ.c linux-3.2/drivers/scst/scst_targ.c ---- orig/linux-3.2/drivers/scst/scst_targ.c -+++ linux-3.2/drivers/scst/scst_targ.c -@@ -0,0 +1,6705 @@ -+/* -+ * scst_targ.c -+ * -+ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net> -+ * Copyright (C) 2004 - 2005 Leonid Stoljar -+ * Copyright (C) 2007 - 2010 ID7 Ltd. -+ * Copyright (C) 2010 - 2011 SCST Ltd. -+ * -+ * 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, version 2 -+ * of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/slab.h> -+#include <linux/sched.h> -+#include <linux/unistd.h> -+#include <linux/string.h> -+#include <linux/kthread.h> -+#include <linux/delay.h> -+#include <linux/ktime.h> -+ -+#include <scst/scst.h> -+#include "scst_priv.h" -+#include "scst_pres.h" -+ -+#if 0 /* Let's disable it for now to see if users will complain about it */ -+/* Deleting it don't forget to delete dev_cmd_count */ -+#define CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT -+#endif -+ -+static void scst_cmd_set_sn(struct scst_cmd *cmd); -+static int __scst_init_cmd(struct scst_cmd *cmd); -+static void scst_finish_cmd_mgmt(struct scst_cmd *cmd); -+static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, -+ uint64_t tag, bool to_abort); -+static void scst_process_redirect_cmd(struct scst_cmd *cmd, -+ enum scst_exec_context context, int check_retries); -+ -+/** -+ * scst_post_parse() - do post parse actions -+ * -+ * This function must be called by dev handler after its parse() callback -+ * returned SCST_CMD_STATE_STOP before calling scst_process_active_cmd(). -+ */ -+void scst_post_parse(struct scst_cmd *cmd) -+{ -+ scst_set_parse_time(cmd); -+} -+EXPORT_SYMBOL_GPL(scst_post_parse); -+ -+/** -+ * scst_post_alloc_data_buf() - do post alloc_data_buf actions -+ * -+ * This function must be called by dev handler after its alloc_data_buf() -+ * callback returned SCST_CMD_STATE_STOP before calling -+ * scst_process_active_cmd(). -+ */ -+void scst_post_alloc_data_buf(struct scst_cmd *cmd) -+{ -+ scst_set_alloc_buf_time(cmd); -+} -+EXPORT_SYMBOL_GPL(scst_post_alloc_data_buf); -+ -+static inline void scst_schedule_tasklet(struct scst_cmd *cmd) -+{ -+ struct scst_percpu_info *i = &scst_percpu_infos[smp_processor_id()]; -+ unsigned long flags; -+ -+ if (atomic_read(&i->cpu_cmd_count) <= scst_max_tasklet_cmd) { -+ spin_lock_irqsave(&i->tasklet_lock, flags); -+ TRACE_DBG("Adding cmd %p to tasklet %d cmd list", cmd, -+ smp_processor_id()); -+ list_add_tail(&cmd->cmd_list_entry, &i->tasklet_cmd_list); -+ spin_unlock_irqrestore(&i->tasklet_lock, flags); -+ -+ tasklet_schedule(&i->tasklet); -+ } else { -+ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags); -+ TRACE_DBG("Too many tasklet commands (%d), adding cmd %p to " -+ "active cmd list", atomic_read(&i->cpu_cmd_count), cmd); -+ list_add_tail(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ wake_up(&cmd->cmd_threads->cmd_list_waitQ); -+ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags); -+ } -+ return; -+} -+ -+/* No locks */ -+static bool scst_check_blocked_dev(struct scst_cmd *cmd) -+{ -+ bool res; -+ struct scst_device *dev = cmd->dev; -+ -+ spin_lock_bh(&dev->dev_lock); -+ -+ dev->on_dev_cmd_count++; -+ cmd->dec_on_dev_needed = 1; -+ TRACE_DBG("New inc on_dev_count %d (cmd %p)", dev->on_dev_cmd_count, -+ cmd); -+ -+ scst_inc_pr_readers_count(cmd, true); -+ -+ if (unlikely(dev->block_count > 0) || -+ unlikely(dev->dev_double_ua_possible) || -+ unlikely(scst_is_serialized_cmd(cmd))) -+ res = __scst_check_blocked_dev(cmd); -+ else -+ res = false; -+ -+ if (unlikely(res)) { -+ /* Undo increments */ -+ dev->on_dev_cmd_count--; -+ cmd->dec_on_dev_needed = 0; -+ TRACE_DBG("New dec on_dev_count %d (cmd %p)", -+ dev->on_dev_cmd_count, cmd); -+ -+ scst_dec_pr_readers_count(cmd, true); -+ } -+ -+ spin_unlock_bh(&dev->dev_lock); -+ -+ return res; -+} -+ -+/* No locks */ -+static void scst_check_unblock_dev(struct scst_cmd *cmd) -+{ -+ struct scst_device *dev = cmd->dev; -+ -+ spin_lock_bh(&dev->dev_lock); -+ -+ if (likely(cmd->dec_on_dev_needed)) { -+ dev->on_dev_cmd_count--; -+ cmd->dec_on_dev_needed = 0; -+ TRACE_DBG("New dec on_dev_count %d (cmd %p)", -+ dev->on_dev_cmd_count, cmd); -+ } -+ -+ if (unlikely(cmd->dec_pr_readers_count_needed)) -+ scst_dec_pr_readers_count(cmd, true); -+ -+ if (unlikely(cmd->unblock_dev)) { -+ TRACE_MGMT_DBG("cmd %p (tag %llu): unblocking dev %s", cmd, -+ (long long unsigned int)cmd->tag, dev->virt_name); -+ cmd->unblock_dev = 0; -+ scst_unblock_dev(dev); -+ } else if (unlikely(dev->strictly_serialized_cmd_waiting)) { -+ if (dev->on_dev_cmd_count == 0) { -+ TRACE_MGMT_DBG("Strictly serialized cmd waiting: " -+ "unblocking dev %s", dev->virt_name); -+ scst_unblock_dev(dev); -+ } -+ } -+ -+ spin_unlock_bh(&dev->dev_lock); -+ return; -+} -+ -+/** -+ * scst_rx_cmd() - create new command -+ * @sess: SCST session -+ * @lun: LUN for the command -+ * @lun_len: length of the LUN in bytes -+ * @cdb: CDB of the command -+ * @cdb_len: length of the CDB in bytes -+ * @atomic: true, if current context is atomic -+ * -+ * Description: -+ * Creates new SCST command. Returns new command on success or -+ * NULL otherwise. -+ * -+ * Must not be called in parallel with scst_unregister_session() for the -+ * same session. -+ */ -+struct scst_cmd *scst_rx_cmd(struct scst_session *sess, -+ const uint8_t *lun, int lun_len, const uint8_t *cdb, -+ unsigned int cdb_len, int atomic) -+{ -+ struct scst_cmd *cmd; -+ -+ TRACE_ENTRY(); -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) { -+ PRINT_CRIT_ERROR("%s", -+ "New cmd while shutting down the session"); -+ BUG(); -+ } -+#endif -+ -+ cmd = scst_alloc_cmd(cdb, cdb_len, atomic ? GFP_ATOMIC : GFP_KERNEL); -+ if (unlikely(cmd == NULL)) -+ goto out; -+ -+ cmd->sess = sess; -+ cmd->tgt = sess->tgt; -+ cmd->tgtt = sess->tgt->tgtt; -+ -+ cmd->lun = scst_unpack_lun(lun, lun_len); -+ if (unlikely(cmd->lun == NO_SUCH_LUN)) -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_lun_not_supported)); -+ -+ TRACE_DBG("cmd %p, sess %p", cmd, sess); -+ scst_sess_get(sess); -+ -+out: -+ TRACE_EXIT(); -+ return cmd; -+} -+EXPORT_SYMBOL(scst_rx_cmd); -+ -+/* -+ * No locks, but might be on IRQ. Returns 0 on success, <0 if processing of -+ * this command should be stopped. -+ */ -+static int scst_init_cmd(struct scst_cmd *cmd, enum scst_exec_context *context) -+{ -+ int rc, res = 0; -+ -+ TRACE_ENTRY(); -+ -+ /* See the comment in scst_do_job_init() */ -+ if (unlikely(!list_empty(&scst_init_cmd_list))) { -+ TRACE_MGMT_DBG("%s", "init cmd list busy"); -+ goto out_redirect; -+ } -+ /* -+ * Memory barrier isn't necessary here, because CPU appears to -+ * be self-consistent and we don't care about the race, described -+ * in comment in scst_do_job_init(). -+ */ -+ -+ rc = __scst_init_cmd(cmd); -+ if (unlikely(rc > 0)) -+ goto out_redirect; -+ else if (unlikely(rc != 0)) { -+ res = 1; -+ goto out; -+ } -+ -+ EXTRACHECKS_BUG_ON(*context == SCST_CONTEXT_SAME); -+ -+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ -+ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED) -+ goto out; -+#endif -+ -+ /* Small context optimization */ -+ if ((*context == SCST_CONTEXT_TASKLET) || -+ (*context == SCST_CONTEXT_DIRECT_ATOMIC)) { -+ /* -+ * If any data_direction not set, it's SCST_DATA_UNKNOWN, -+ * which is 0, so we can safely | them -+ */ -+ BUILD_BUG_ON(SCST_DATA_UNKNOWN != 0); -+ if ((cmd->data_direction | cmd->expected_data_direction) & SCST_DATA_WRITE) { -+ if (!test_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC, -+ &cmd->tgt_dev->tgt_dev_flags)) -+ *context = SCST_CONTEXT_THREAD; -+ } else -+ *context = SCST_CONTEXT_THREAD; -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_redirect: -+ if (cmd->preprocessing_only) { -+ /* -+ * Poor man solution for single threaded targets, where -+ * blocking receiver at least sometimes means blocking all. -+ * For instance, iSCSI target won't be able to receive -+ * Data-Out PDUs. -+ */ -+ BUG_ON(*context != SCST_CONTEXT_DIRECT); -+ scst_set_busy(cmd); -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = 1; -+ /* Keep initiator away from too many BUSY commands */ -+ msleep(50); -+ } else { -+ unsigned long flags; -+ spin_lock_irqsave(&scst_init_lock, flags); -+ TRACE_MGMT_DBG("Adding cmd %p to init cmd list)", cmd); -+ list_add_tail(&cmd->cmd_list_entry, &scst_init_cmd_list); -+ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) -+ scst_init_poll_cnt++; -+ spin_unlock_irqrestore(&scst_init_lock, flags); -+ wake_up(&scst_init_cmd_list_waitQ); -+ res = -1; -+ } -+ goto out; -+} -+ -+/** -+ * scst_cmd_init_done() - the command's initialization done -+ * @cmd: SCST command -+ * @pref_context: preferred command execution context -+ * -+ * Description: -+ * Notifies SCST that the driver finished its part of the command -+ * initialization, and the command is ready for execution. -+ * The second argument sets preferred command execution context. -+ * See SCST_CONTEXT_* constants for details. -+ * -+ * !!IMPORTANT!! -+ * -+ * If cmd->set_sn_on_restart_cmd not set, this function, as well as -+ * scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be -+ * called simultaneously for the same session (more precisely, -+ * for the same session/LUN, i.e. tgt_dev), i.e. they must be -+ * somehow externally serialized. This is needed to have lock free fast -+ * path in scst_cmd_set_sn(). For majority of targets those functions are -+ * naturally serialized by the single source of commands. Only iSCSI -+ * immediate commands with multiple connections per session seems to be an -+ * exception. For it, some mutex/lock shall be used for the serialization. -+ */ -+void scst_cmd_init_done(struct scst_cmd *cmd, -+ enum scst_exec_context pref_context) -+{ -+ unsigned long flags; -+ struct scst_session *sess = cmd->sess; -+ int rc; -+ -+ TRACE_ENTRY(); -+ -+ scst_set_start_time(cmd); -+ -+ TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd); -+ TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d, queue_type=%x " -+ "(cmd %p, sess %p)", (long long unsigned int)cmd->tag, -+ (long long unsigned int)cmd->lun, cmd->cdb_len, -+ cmd->queue_type, cmd, sess); -+ PRINT_BUFF_FLAG(TRACE_SCSI|TRACE_RCV_BOT, "Receiving CDB", -+ cmd->cdb, cmd->cdb_len); -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if (unlikely((in_irq() || irqs_disabled())) && -+ ((pref_context == SCST_CONTEXT_DIRECT) || -+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) { -+ PRINT_ERROR("Wrong context %d in IRQ from target %s, use " -+ "SCST_CONTEXT_THREAD instead", pref_context, -+ cmd->tgtt->name); -+ dump_stack(); -+ pref_context = SCST_CONTEXT_THREAD; -+ } -+#endif -+ -+ atomic_inc(&sess->sess_cmd_count); -+ -+ spin_lock_irqsave(&sess->sess_list_lock, flags); -+ -+ if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) { -+ /* -+ * We must always keep commands in the sess list from the -+ * very beginning, because otherwise they can be missed during -+ * TM processing. This check is needed because there might be -+ * old, i.e. deferred, commands and new, i.e. just coming, ones. -+ */ -+ if (cmd->sess_cmd_list_entry.next == NULL) -+ list_add_tail(&cmd->sess_cmd_list_entry, -+ &sess->sess_cmd_list); -+ switch (sess->init_phase) { -+ case SCST_SESS_IPH_SUCCESS: -+ break; -+ case SCST_SESS_IPH_INITING: -+ TRACE_DBG("Adding cmd %p to init deferred cmd list", -+ cmd); -+ list_add_tail(&cmd->cmd_list_entry, -+ &sess->init_deferred_cmd_list); -+ spin_unlock_irqrestore(&sess->sess_list_lock, flags); -+ goto out; -+ case SCST_SESS_IPH_FAILED: -+ spin_unlock_irqrestore(&sess->sess_list_lock, flags); -+ scst_set_busy(cmd); -+ goto set_state; -+ default: -+ BUG(); -+ } -+ } else -+ list_add_tail(&cmd->sess_cmd_list_entry, -+ &sess->sess_cmd_list); -+ -+ spin_unlock_irqrestore(&sess->sess_list_lock, flags); -+ -+ if (unlikely(cmd->queue_type >= SCST_CMD_QUEUE_ACA)) { -+ PRINT_ERROR("Unsupported queue type %d", cmd->queue_type); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_message)); -+ } -+ -+set_state: -+ if (unlikely(cmd->status != SAM_STAT_GOOD)) { -+ scst_set_cmd_abnormal_done_state(cmd); -+ goto active; -+ } -+ -+ /* -+ * Cmd must be inited here to preserve the order. In case if cmd -+ * already preliminary completed by target driver we need to init -+ * cmd anyway to find out in which format we should return sense. -+ */ -+ cmd->state = SCST_CMD_STATE_INIT; -+ rc = scst_init_cmd(cmd, &pref_context); -+ if (unlikely(rc < 0)) -+ goto out; -+ -+active: -+ /* Here cmd must not be in any cmd list, no locks */ -+ switch (pref_context) { -+ case SCST_CONTEXT_TASKLET: -+ scst_schedule_tasklet(cmd); -+ break; -+ -+ default: -+ PRINT_ERROR("Context %x is undefined, using the thread one", -+ pref_context); -+ /* go through */ -+ case SCST_CONTEXT_THREAD: -+ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags); -+ TRACE_DBG("Adding cmd %p to active cmd list", cmd); -+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE)) -+ list_add(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ else -+ list_add_tail(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ wake_up(&cmd->cmd_threads->cmd_list_waitQ); -+ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags); -+ break; -+ -+ case SCST_CONTEXT_DIRECT: -+ scst_process_active_cmd(cmd, false); -+ break; -+ -+ case SCST_CONTEXT_DIRECT_ATOMIC: -+ scst_process_active_cmd(cmd, true); -+ break; -+ } -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL(scst_cmd_init_done); -+ -+int scst_pre_parse(struct scst_cmd *cmd) -+{ -+ int res; -+ struct scst_device *dev = cmd->dev; -+ int rc; -+ -+ TRACE_ENTRY(); -+ -+ /* -+ * Expected transfer data supplied by the SCSI transport via the -+ * target driver are untrusted, so we prefer to fetch them from CDB. -+ * Additionally, not all transports support supplying the expected -+ * transfer data. -+ */ -+ -+ rc = scst_get_cdb_info(cmd); -+ if (unlikely(rc != 0)) { -+ if (rc > 0) { -+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); -+ goto out_err; -+ } -+ -+ EXTRACHECKS_BUG_ON(cmd->op_flags & SCST_INFO_VALID); -+ -+ TRACE(TRACE_MINOR, "Unknown opcode 0x%02x for %s. " -+ "Should you update scst_scsi_op_table?", -+ cmd->cdb[0], dev->handler->name); -+ PRINT_BUFF_FLAG(TRACE_MINOR, "Failed CDB", cmd->cdb, -+ cmd->cdb_len); -+ } else -+ EXTRACHECKS_BUG_ON(!(cmd->op_flags & SCST_INFO_VALID)); -+ -+#ifdef CONFIG_SCST_STRICT_SERIALIZING -+ cmd->inc_expected_sn_on_done = 1; -+#else -+ cmd->inc_expected_sn_on_done = dev->handler->exec_sync || -+ (!dev->has_own_order_mgmt && -+ (dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER || -+ cmd->queue_type == SCST_CMD_QUEUE_ORDERED)); -+#endif -+ -+ TRACE_DBG("op_name <%s> (cmd %p), direction=%d " -+ "(expected %d, set %s), bufflen=%d, out_bufflen=%d (expected " -+ "len %d, out expected len %d), flags=0x%x", cmd->op_name, cmd, -+ cmd->data_direction, cmd->expected_data_direction, -+ scst_cmd_is_expected_set(cmd) ? "yes" : "no", -+ cmd->bufflen, cmd->out_bufflen, cmd->expected_transfer_len, -+ cmd->expected_out_transfer_len, cmd->op_flags); -+ -+ res = 0; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_err: -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = -1; -+ goto out; -+} -+ -+#ifndef CONFIG_SCST_USE_EXPECTED_VALUES -+static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd) -+{ -+ bool res = false; -+ -+ /* VERIFY commands with BYTCHK unset shouldn't fail here */ -+ if ((cmd->op_flags & SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED) && -+ (cmd->cdb[1] & BYTCHK) == 0) { -+ res = true; -+ goto out; -+ } -+ -+ switch (cmd->cdb[0]) { -+ case TEST_UNIT_READY: -+ /* Crazy VMware people sometimes do TUR with READ direction */ -+ if ((cmd->expected_data_direction == SCST_DATA_READ) || -+ (cmd->expected_data_direction == SCST_DATA_NONE)) -+ res = true; -+ break; -+ } -+ -+out: -+ return res; -+} -+#endif -+ -+static int scst_parse_cmd(struct scst_cmd *cmd) -+{ -+ int res = SCST_CMD_STATE_RES_CONT_SAME; -+ int state; -+ struct scst_device *dev = cmd->dev; -+ int orig_bufflen = cmd->bufflen; -+ -+ TRACE_ENTRY(); -+ -+ if (likely(!scst_is_cmd_fully_local(cmd))) { -+ if (unlikely(!dev->handler->parse_atomic && -+ scst_cmd_atomic(cmd))) { -+ /* -+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_* -+ * optimization. -+ */ -+ TRACE_MGMT_DBG("Dev handler %s parse() needs thread " -+ "context, rescheduling", dev->handler->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ TRACE_DBG("Calling dev handler %s parse(%p)", -+ dev->handler->name, cmd); -+ TRACE_BUFF_FLAG(TRACE_SND_BOT, "Parsing: ", -+ cmd->cdb, cmd->cdb_len); -+ scst_set_cur_start(cmd); -+ state = dev->handler->parse(cmd); -+ /* Caution: cmd can be already dead here */ -+ TRACE_DBG("Dev handler %s parse() returned %d", -+ dev->handler->name, state); -+ -+ switch (state) { -+ case SCST_CMD_STATE_NEED_THREAD_CTX: -+ scst_set_parse_time(cmd); -+ TRACE_DBG("Dev handler %s parse() requested thread " -+ "context, rescheduling", dev->handler->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ -+ case SCST_CMD_STATE_STOP: -+ TRACE_DBG("Dev handler %s parse() requested stop " -+ "processing", dev->handler->name); -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ goto out; -+ } -+ -+ scst_set_parse_time(cmd); -+ -+ if (state == SCST_CMD_STATE_DEFAULT) -+ state = SCST_CMD_STATE_PREPARE_SPACE; -+ } else -+ state = SCST_CMD_STATE_PREPARE_SPACE; -+ -+ if (unlikely(state == SCST_CMD_STATE_PRE_XMIT_RESP)) -+ goto set_res; -+ -+ if (unlikely(!(cmd->op_flags & SCST_INFO_VALID))) { -+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES -+ if (scst_cmd_is_expected_set(cmd)) { -+ TRACE(TRACE_MINOR, "Using initiator supplied values: " -+ "direction %d, transfer_len %d/%d", -+ cmd->expected_data_direction, -+ cmd->expected_transfer_len, -+ cmd->expected_out_transfer_len); -+ cmd->data_direction = cmd->expected_data_direction; -+ cmd->bufflen = cmd->expected_transfer_len; -+ cmd->out_bufflen = cmd->expected_out_transfer_len; -+ } else { -+ PRINT_ERROR("Unknown opcode 0x%02x for %s and " -+ "target %s not supplied expected values", -+ cmd->cdb[0], dev->handler->name, cmd->tgtt->name); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); -+ goto out_done; -+ } -+#else -+ /* -+ * Let's ignore reporting T10/04-262r7 16-byte and 12-byte ATA -+ * pass-thru commands to not pollute logs (udev(?) checks them -+ * for some reason). If somebody has their description, please, -+ * update scst_scsi_op_table. -+ */ -+ if ((cmd->cdb[0] != 0x85) && (cmd->cdb[0] != 0xa1)) -+ PRINT_ERROR("Refusing unknown opcode %x", cmd->cdb[0]); -+ else -+ TRACE(TRACE_MINOR, "Refusing unknown opcode %x", -+ cmd->cdb[0]); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); -+ goto out_done; -+#endif -+ } -+ -+ if (unlikely(cmd->cdb_len == 0)) { -+ PRINT_ERROR("Unable to get CDB length for " -+ "opcode 0x%02x. Returning INVALID " -+ "OPCODE", cmd->cdb[0]); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); -+ goto out_done; -+ } -+ -+ EXTRACHECKS_BUG_ON(cmd->cdb_len == 0); -+ -+ TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d " -+ "(expected %d, set %s), bufflen=%d, out_bufflen=%d, (expected " -+ "len %d, out expected len %d), flags=%x", cmd->op_name, cmd, -+ cmd->data_direction, cmd->expected_data_direction, -+ scst_cmd_is_expected_set(cmd) ? "yes" : "no", -+ cmd->bufflen, cmd->out_bufflen, cmd->expected_transfer_len, -+ cmd->expected_out_transfer_len, cmd->op_flags); -+ -+ if (unlikely((cmd->op_flags & SCST_UNKNOWN_LENGTH) != 0)) { -+ if (scst_cmd_is_expected_set(cmd)) { -+ /* -+ * Command data length can't be easily -+ * determined from the CDB. ToDo, all such -+ * commands processing should be fixed. Until -+ * it's done, get the length from the supplied -+ * expected value, but limit it to some -+ * reasonable value (15MB). -+ */ -+ cmd->bufflen = min(cmd->expected_transfer_len, -+ 15*1024*1024); -+ if (cmd->data_direction == SCST_DATA_BIDI) -+ cmd->out_bufflen = min(cmd->expected_out_transfer_len, -+ 15*1024*1024); -+ cmd->op_flags &= ~SCST_UNKNOWN_LENGTH; -+ } else { -+ PRINT_ERROR("Unknown data transfer length for opcode " -+ "0x%x (handler %s, target %s)", cmd->cdb[0], -+ dev->handler->name, cmd->tgtt->name); -+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_message)); -+ goto out_done; -+ } -+ } -+ -+ if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) { -+ PRINT_ERROR("NACA bit in control byte CDB is not supported " -+ "(opcode 0x%02x)", cmd->cdb[0]); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_done; -+ } -+ -+ if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) { -+ PRINT_ERROR("Linked commands are not supported " -+ "(opcode 0x%02x)", cmd->cdb[0]); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_done; -+ } -+ -+ if (cmd->dh_data_buf_alloced && -+ unlikely((orig_bufflen > cmd->bufflen))) { -+ PRINT_ERROR("Dev handler supplied data buffer (size %d), " -+ "is less, than required (size %d)", cmd->bufflen, -+ orig_bufflen); -+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); -+ goto out_hw_error; -+ } -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if ((cmd->bufflen != 0) && -+ ((cmd->data_direction == SCST_DATA_NONE) || -+ ((cmd->sg == NULL) && (state > SCST_CMD_STATE_PREPARE_SPACE)))) { -+ PRINT_ERROR("Dev handler %s parse() returned " -+ "invalid cmd data_direction %d, bufflen %d, state %d " -+ "or sg %p (opcode 0x%x)", dev->handler->name, -+ cmd->data_direction, cmd->bufflen, state, cmd->sg, -+ cmd->cdb[0]); -+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); -+ goto out_hw_error; -+ } -+#endif -+ -+ if (scst_cmd_is_expected_set(cmd)) { -+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES -+ if (unlikely((cmd->data_direction != cmd->expected_data_direction) || -+ (cmd->bufflen != cmd->expected_transfer_len) || -+ (cmd->out_bufflen != cmd->expected_out_transfer_len))) { -+ TRACE(TRACE_MINOR, "Expected values don't match " -+ "decoded ones: data_direction %d, " -+ "expected_data_direction %d, " -+ "bufflen %d, expected_transfer_len %d, " -+ "out_bufflen %d, expected_out_transfer_len %d", -+ cmd->data_direction, -+ cmd->expected_data_direction, -+ cmd->bufflen, cmd->expected_transfer_len, -+ cmd->out_bufflen, cmd->expected_out_transfer_len); -+ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB", -+ cmd->cdb, cmd->cdb_len); -+ cmd->data_direction = cmd->expected_data_direction; -+ cmd->bufflen = cmd->expected_transfer_len; -+ cmd->out_bufflen = cmd->expected_out_transfer_len; -+ cmd->resid_possible = 1; -+ } -+#else -+ if (unlikely(cmd->data_direction != -+ cmd->expected_data_direction)) { -+ if (((cmd->expected_data_direction != SCST_DATA_NONE) || -+ (cmd->bufflen != 0)) && -+ !scst_is_allowed_to_mismatch_cmd(cmd)) { -+ PRINT_ERROR("Expected data direction %d for " -+ "opcode 0x%02x (handler %s, target %s) " -+ "doesn't match decoded value %d", -+ cmd->expected_data_direction, -+ cmd->cdb[0], dev->handler->name, -+ cmd->tgtt->name, cmd->data_direction); -+ PRINT_BUFFER("Failed CDB", cmd->cdb, -+ cmd->cdb_len); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_message)); -+ goto out_done; -+ } -+ } -+ if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) { -+ TRACE(TRACE_MINOR, "Warning: expected " -+ "transfer length %d for opcode 0x%02x " -+ "(handler %s, target %s) doesn't match " -+ "decoded value %d", -+ cmd->expected_transfer_len, cmd->cdb[0], -+ dev->handler->name, cmd->tgtt->name, -+ cmd->bufflen); -+ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB", -+ cmd->cdb, cmd->cdb_len); -+ if ((cmd->data_direction & SCST_DATA_READ) || -+ (cmd->data_direction & SCST_DATA_WRITE)) -+ cmd->resid_possible = 1; -+ } -+ if (unlikely(cmd->out_bufflen != cmd->expected_out_transfer_len)) { -+ TRACE(TRACE_MINOR, "Warning: expected bidirectional OUT " -+ "transfer length %d for opcode 0x%02x " -+ "(handler %s, target %s) doesn't match " -+ "decoded value %d", -+ cmd->expected_out_transfer_len, cmd->cdb[0], -+ dev->handler->name, cmd->tgtt->name, -+ cmd->out_bufflen); -+ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB", -+ cmd->cdb, cmd->cdb_len); -+ cmd->resid_possible = 1; -+ } -+#endif -+ } -+ -+ if (unlikely(cmd->data_direction == SCST_DATA_UNKNOWN)) { -+ PRINT_ERROR("Unknown data direction. Opcode 0x%x, handler %s, " -+ "target %s", cmd->cdb[0], dev->handler->name, -+ cmd->tgtt->name); -+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); -+ goto out_hw_error; -+ } -+ -+set_res: -+ if (cmd->data_len == -1) -+ cmd->data_len = cmd->bufflen; -+ -+ if (cmd->bufflen == 0) { -+ /* -+ * According to SPC bufflen 0 for data transfer commands isn't -+ * an error, so we need to fix the transfer direction. -+ */ -+ cmd->data_direction = SCST_DATA_NONE; -+ } -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ switch (state) { -+ case SCST_CMD_STATE_PREPARE_SPACE: -+ case SCST_CMD_STATE_PARSE: -+ case SCST_CMD_STATE_RDY_TO_XFER: -+ case SCST_CMD_STATE_TGT_PRE_EXEC: -+ case SCST_CMD_STATE_SEND_FOR_EXEC: -+ case SCST_CMD_STATE_START_EXEC: -+ case SCST_CMD_STATE_LOCAL_EXEC: -+ case SCST_CMD_STATE_REAL_EXEC: -+ case SCST_CMD_STATE_PRE_DEV_DONE: -+ case SCST_CMD_STATE_DEV_DONE: -+ case SCST_CMD_STATE_PRE_XMIT_RESP: -+ case SCST_CMD_STATE_XMIT_RESP: -+ case SCST_CMD_STATE_FINISHED: -+ case SCST_CMD_STATE_FINISHED_INTERNAL: -+#endif -+ cmd->state = state; -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+#ifdef CONFIG_SCST_EXTRACHECKS -+ break; -+ -+ default: -+ if (state >= 0) { -+ PRINT_ERROR("Dev handler %s parse() returned " -+ "invalid cmd state %d (opcode %d)", -+ dev->handler->name, state, cmd->cdb[0]); -+ } else { -+ PRINT_ERROR("Dev handler %s parse() returned " -+ "error %d (opcode %d)", dev->handler->name, -+ state, cmd->cdb[0]); -+ } -+ goto out_hw_error; -+ } -+#endif -+ -+ if (cmd->resp_data_len == -1) { -+ if (cmd->data_direction & SCST_DATA_READ) -+ cmd->resp_data_len = cmd->bufflen; -+ else -+ cmd->resp_data_len = 0; -+ } -+ -+ /* We already completed (with an error) */ -+ if (unlikely(cmd->completed)) -+ goto out_done; -+ -+#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ -+ /* -+ * We can't allow atomic command on the exec stages. It shouldn't -+ * be because of the SCST_TGT_DEV_AFTER_* optimization, but during -+ * parsing data_direction can change, so we need to recheck. -+ */ -+ if (unlikely(scst_cmd_atomic(cmd) && -+ !(cmd->data_direction & SCST_DATA_WRITE))) { -+ TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_MINOR, "Atomic context and " -+ "non-WRITE data direction, rescheduling (cmd %p)", cmd); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+#endif -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+ -+out_hw_error: -+ /* dev_done() will be called as part of the regular cmd's finish */ -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ -+out_done: -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+} -+ -+static void scst_set_write_len(struct scst_cmd *cmd) -+{ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(!(cmd->data_direction & SCST_DATA_WRITE)); -+ -+ if (cmd->data_direction & SCST_DATA_READ) { -+ cmd->write_len = cmd->out_bufflen; -+ cmd->write_sg = &cmd->out_sg; -+ cmd->write_sg_cnt = &cmd->out_sg_cnt; -+ } else { -+ cmd->write_len = cmd->bufflen; -+ /* write_sg and write_sg_cnt already initialized correctly */ -+ } -+ -+ TRACE_MEM("cmd %p, write_len %d, write_sg %p, write_sg_cnt %d, " -+ "resid_possible %d", cmd, cmd->write_len, *cmd->write_sg, -+ *cmd->write_sg_cnt, cmd->resid_possible); -+ -+ if (unlikely(cmd->resid_possible)) { -+ if (cmd->data_direction & SCST_DATA_READ) { -+ cmd->write_len = min(cmd->out_bufflen, -+ cmd->expected_out_transfer_len); -+ if (cmd->write_len == cmd->out_bufflen) -+ goto out; -+ } else { -+ cmd->write_len = min(cmd->bufflen, -+ cmd->expected_transfer_len); -+ if (cmd->write_len == cmd->bufflen) -+ goto out; -+ } -+ scst_limit_sg_write_len(cmd); -+ } -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+ -+static int scst_prepare_space(struct scst_cmd *cmd) -+{ -+ int r = 0, res = SCST_CMD_STATE_RES_CONT_SAME; -+ struct scst_device *dev = cmd->dev; -+ -+ TRACE_ENTRY(); -+ -+ if (cmd->data_direction == SCST_DATA_NONE) -+ goto done; -+ -+ if (likely(!scst_is_cmd_fully_local(cmd)) && -+ (dev->handler->alloc_data_buf != NULL)) { -+ int state; -+ -+ if (unlikely(!dev->handler->alloc_data_buf_atomic && -+ scst_cmd_atomic(cmd))) { -+ /* -+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_* -+ * optimization. -+ */ -+ TRACE_MGMT_DBG("Dev handler %s alloc_data_buf() needs " -+ "thread context, rescheduling", -+ dev->handler->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ TRACE_DBG("Calling dev handler %s alloc_data_buf(%p)", -+ dev->handler->name, cmd); -+ scst_set_cur_start(cmd); -+ state = dev->handler->alloc_data_buf(cmd); -+ /* Caution: cmd can be already dead here */ -+ TRACE_DBG("Dev handler %s alloc_data_buf() returned %d", -+ dev->handler->name, state); -+ -+ switch (state) { -+ case SCST_CMD_STATE_NEED_THREAD_CTX: -+ scst_set_alloc_buf_time(cmd); -+ TRACE_DBG("Dev handler %s alloc_data_buf() requested " -+ "thread context, rescheduling", -+ dev->handler->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ -+ case SCST_CMD_STATE_STOP: -+ TRACE_DBG("Dev handler %s alloc_data_buf() requested " -+ "stop processing", dev->handler->name); -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ goto out; -+ } -+ -+ scst_set_alloc_buf_time(cmd); -+ -+ if (unlikely(state != SCST_CMD_STATE_DEFAULT)) { -+ cmd->state = state; -+ goto out; -+ } -+ } -+ -+ if (cmd->tgt_need_alloc_data_buf) { -+ int orig_bufflen = cmd->bufflen; -+ -+ TRACE_MEM("Custom tgt data buf allocation requested (cmd %p)", -+ cmd); -+ -+ scst_set_cur_start(cmd); -+ r = cmd->tgtt->alloc_data_buf(cmd); -+ scst_set_alloc_buf_time(cmd); -+ -+ if (r > 0) -+ goto alloc; -+ else if (r == 0) { -+ if (unlikely(cmd->bufflen == 0)) { -+ /* See comment in scst_alloc_space() */ -+ if (cmd->sg == NULL) -+ goto alloc; -+ } -+ -+ cmd->tgt_data_buf_alloced = 1; -+ -+ if (unlikely(orig_bufflen < cmd->bufflen)) { -+ PRINT_ERROR("Target driver allocated data " -+ "buffer (size %d), is less, than " -+ "required (size %d)", orig_bufflen, -+ cmd->bufflen); -+ goto out_error; -+ } -+ TRACE_MEM("tgt_data_buf_alloced (cmd %p)", cmd); -+ } else -+ goto check; -+ } -+ -+alloc: -+ if (!cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) { -+ r = scst_alloc_space(cmd); -+ } else if (cmd->dh_data_buf_alloced && !cmd->tgt_data_buf_alloced) { -+ TRACE_MEM("dh_data_buf_alloced set (cmd %p)", cmd); -+ r = 0; -+ } else if (cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) { -+ TRACE_MEM("tgt_data_buf_alloced set (cmd %p)", cmd); -+ cmd->sg = cmd->tgt_sg; -+ cmd->sg_cnt = cmd->tgt_sg_cnt; -+ cmd->out_sg = cmd->tgt_out_sg; -+ cmd->out_sg_cnt = cmd->tgt_out_sg_cnt; -+ r = 0; -+ } else { -+ TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, " -+ "sg_cnt %d, tgt_sg %p, tgt_sg_cnt %d)", cmd, cmd->sg, -+ cmd->sg_cnt, cmd->tgt_sg, cmd->tgt_sg_cnt); -+ r = 0; -+ } -+ -+check: -+ if (r != 0) { -+ if (scst_cmd_atomic(cmd)) { -+ TRACE_MEM("%s", "Atomic memory allocation failed, " -+ "rescheduling to the thread"); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } else -+ goto out_no_space; -+ } -+ -+done: -+ if (cmd->preprocessing_only) { -+ cmd->state = SCST_CMD_STATE_PREPROCESSING_DONE; -+ if (cmd->data_direction & SCST_DATA_WRITE) -+ scst_set_write_len(cmd); -+ } else if (cmd->data_direction & SCST_DATA_WRITE) { -+ cmd->state = SCST_CMD_STATE_RDY_TO_XFER; -+ scst_set_write_len(cmd); -+ } else -+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC; -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+ -+out_no_space: -+ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate or build requested buffer " -+ "(size %d), sending BUSY or QUEUE FULL status", cmd->bufflen); -+ scst_set_busy(cmd); -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+ -+out_error: -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+} -+ -+static int scst_preprocessing_done(struct scst_cmd *cmd) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(!cmd->preprocessing_only); -+ -+ cmd->preprocessing_only = 0; -+ -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ cmd->state = SCST_CMD_STATE_PREPROCESSING_DONE_CALLED; -+ -+ TRACE_DBG("Calling preprocessing_done(cmd %p)", cmd); -+ scst_set_cur_start(cmd); -+ cmd->tgtt->preprocessing_done(cmd); -+ TRACE_DBG("%s", "preprocessing_done() returned"); -+ -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/** -+ * scst_restart_cmd() - restart execution of the command -+ * @cmd: SCST commands -+ * @status: completion status -+ * @pref_context: preferred command execution context -+ * -+ * Description: -+ * Notifies SCST that the driver finished its part of the command's -+ * preprocessing and it is ready for further processing. -+ * -+ * The second argument sets completion status -+ * (see SCST_PREPROCESS_STATUS_* constants for details) -+ * -+ * See also comment for scst_cmd_init_done() for the serialization -+ * requirements. -+ */ -+void scst_restart_cmd(struct scst_cmd *cmd, int status, -+ enum scst_exec_context pref_context) -+{ -+ TRACE_ENTRY(); -+ -+ scst_set_restart_waiting_time(cmd); -+ -+ TRACE_DBG("Preferred context: %d", pref_context); -+ TRACE_DBG("tag=%llu, status=%#x", -+ (long long unsigned int)scst_cmd_get_tag(cmd), -+ status); -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if ((in_irq() || irqs_disabled()) && -+ ((pref_context == SCST_CONTEXT_DIRECT) || -+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) { -+ PRINT_ERROR("Wrong context %d in IRQ from target %s, use " -+ "SCST_CONTEXT_THREAD instead", pref_context, -+ cmd->tgtt->name); -+ dump_stack(); -+ pref_context = SCST_CONTEXT_THREAD; -+ } -+#endif -+ -+ switch (status) { -+ case SCST_PREPROCESS_STATUS_SUCCESS: -+ if (cmd->data_direction & SCST_DATA_WRITE) -+ cmd->state = SCST_CMD_STATE_RDY_TO_XFER; -+ else -+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC; -+ if (cmd->set_sn_on_restart_cmd) -+ scst_cmd_set_sn(cmd); -+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ -+ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED) -+ break; -+#endif -+ /* Small context optimization */ -+ if ((pref_context == SCST_CONTEXT_TASKLET) || -+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) || -+ ((pref_context == SCST_CONTEXT_SAME) && -+ scst_cmd_atomic(cmd))) -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ -+ case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET: -+ scst_set_cmd_abnormal_done_state(cmd); -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ -+ case SCST_PREPROCESS_STATUS_ERROR_FATAL: -+ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags); -+ /* go through */ -+ case SCST_PREPROCESS_STATUS_ERROR: -+ if (cmd->sense != NULL) -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ -+ default: -+ PRINT_ERROR("%s() received unknown status %x", __func__, -+ status); -+ scst_set_cmd_abnormal_done_state(cmd); -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ } -+ -+ scst_process_redirect_cmd(cmd, pref_context, 1); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL(scst_restart_cmd); -+ -+static int scst_rdy_to_xfer(struct scst_cmd *cmd) -+{ -+ int res, rc; -+ struct scst_tgt_template *tgtt = cmd->tgtt; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { -+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd); -+ goto out_dev_done; -+ } -+ -+ if ((tgtt->rdy_to_xfer == NULL) || unlikely(cmd->internal)) { -+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC; -+#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ -+ /* We can't allow atomic command on the exec stages */ -+ if (scst_cmd_atomic(cmd)) { -+ TRACE_DBG("NULL rdy_to_xfer() and atomic context, " -+ "rescheduling (cmd %p)", cmd); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ } else -+#endif -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+ } -+ -+ if (unlikely(!tgtt->rdy_to_xfer_atomic && scst_cmd_atomic(cmd))) { -+ /* -+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_* -+ * optimization. -+ */ -+ TRACE_MGMT_DBG("Target driver %s rdy_to_xfer() needs thread " -+ "context, rescheduling", tgtt->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ while (1) { -+ int finished_cmds = atomic_read(&cmd->tgt->finished_cmds); -+ -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ cmd->state = SCST_CMD_STATE_DATA_WAIT; -+ -+ if (tgtt->on_hw_pending_cmd_timeout != NULL) { -+ struct scst_session *sess = cmd->sess; -+ cmd->hw_pending_start = jiffies; -+ cmd->cmd_hw_pending = 1; -+ if (!test_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags)) { -+ TRACE_DBG("Sched HW pending work for sess %p " -+ "(max time %d)", sess, -+ tgtt->max_hw_pending_time); -+ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, -+ &sess->sess_aflags); -+ schedule_delayed_work(&sess->hw_pending_work, -+ tgtt->max_hw_pending_time * HZ); -+ } -+ } -+ -+ scst_set_cur_start(cmd); -+ -+ TRACE_DBG("Calling rdy_to_xfer(%p)", cmd); -+#ifdef CONFIG_SCST_DEBUG_RETRY -+ if (((scst_random() % 100) == 75)) -+ rc = SCST_TGT_RES_QUEUE_FULL; -+ else -+#endif -+ rc = tgtt->rdy_to_xfer(cmd); -+ TRACE_DBG("rdy_to_xfer() returned %d", rc); -+ -+ if (likely(rc == SCST_TGT_RES_SUCCESS)) -+ goto out; -+ -+ scst_set_rdy_to_xfer_time(cmd); -+ -+ cmd->cmd_hw_pending = 0; -+ -+ /* Restore the previous state */ -+ cmd->state = SCST_CMD_STATE_RDY_TO_XFER; -+ -+ switch (rc) { -+ case SCST_TGT_RES_QUEUE_FULL: -+ if (scst_queue_retry_cmd(cmd, finished_cmds) == 0) -+ break; -+ else -+ continue; -+ -+ case SCST_TGT_RES_NEED_THREAD_CTX: -+ TRACE_DBG("Target driver %s " -+ "rdy_to_xfer() requested thread " -+ "context, rescheduling", tgtt->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ -+ default: -+ goto out_error_rc; -+ } -+ break; -+ } -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+ -+out_error_rc: -+ if (rc == SCST_TGT_RES_FATAL_ERROR) { -+ PRINT_ERROR("Target driver %s rdy_to_xfer() returned " -+ "fatal error", tgtt->name); -+ } else { -+ PRINT_ERROR("Target driver %s rdy_to_xfer() returned invalid " -+ "value %d", tgtt->name, rc); -+ } -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ -+out_dev_done: -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+} -+ -+/* No locks, but might be in IRQ */ -+static void scst_process_redirect_cmd(struct scst_cmd *cmd, -+ enum scst_exec_context context, int check_retries) -+{ -+ struct scst_tgt *tgt = cmd->tgt; -+ unsigned long flags; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_DBG("Context: %x", context); -+ -+ if (check_retries) -+ scst_check_retries(tgt); -+ -+ if (context == SCST_CONTEXT_SAME) -+ context = scst_cmd_atomic(cmd) ? SCST_CONTEXT_DIRECT_ATOMIC : -+ SCST_CONTEXT_DIRECT; -+ -+ switch (context) { -+ case SCST_CONTEXT_DIRECT_ATOMIC: -+ scst_process_active_cmd(cmd, true); -+ break; -+ -+ case SCST_CONTEXT_DIRECT: -+ scst_process_active_cmd(cmd, false); -+ break; -+ -+ case SCST_CONTEXT_TASKLET: -+ scst_schedule_tasklet(cmd); -+ break; -+ -+ default: -+ PRINT_ERROR("Context %x is unknown, using the thread one", -+ context); -+ /* go through */ -+ case SCST_CONTEXT_THREAD: -+ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags); -+ TRACE_DBG("Adding cmd %p to active cmd list", cmd); -+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE)) -+ list_add(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ else -+ list_add_tail(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ wake_up(&cmd->cmd_threads->cmd_list_waitQ); -+ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags); -+ break; -+ } -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/** -+ * scst_rx_data() - the command's data received -+ * @cmd: SCST commands -+ * @status: data receiving completion status -+ * @pref_context: preferred command execution context -+ * -+ * Description: -+ * Notifies SCST that the driver received all the necessary data -+ * and the command is ready for further processing. -+ * -+ * The second argument sets data receiving completion status -+ * (see SCST_RX_STATUS_* constants for details) -+ */ -+void scst_rx_data(struct scst_cmd *cmd, int status, -+ enum scst_exec_context pref_context) -+{ -+ TRACE_ENTRY(); -+ -+ scst_set_rdy_to_xfer_time(cmd); -+ -+ TRACE_DBG("Preferred context: %d", pref_context); -+ TRACE(TRACE_SCSI, "cmd %p, status %#x", cmd, status); -+ -+ cmd->cmd_hw_pending = 0; -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if ((in_irq() || irqs_disabled()) && -+ ((pref_context == SCST_CONTEXT_DIRECT) || -+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) { -+ PRINT_ERROR("Wrong context %d in IRQ from target %s, use " -+ "SCST_CONTEXT_THREAD instead", pref_context, -+ cmd->tgtt->name); -+ dump_stack(); -+ pref_context = SCST_CONTEXT_THREAD; -+ } -+#endif -+ -+ switch (status) { -+ case SCST_RX_STATUS_SUCCESS: -+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) -+ if (trace_flag & TRACE_RCV_BOT) { -+ int i, j; -+ struct scatterlist *sg; -+ if (cmd->out_sg != NULL) -+ sg = cmd->out_sg; -+ else if (cmd->tgt_out_sg != NULL) -+ sg = cmd->tgt_out_sg; -+ else if (cmd->tgt_sg != NULL) -+ sg = cmd->tgt_sg; -+ else -+ sg = cmd->sg; -+ if (sg != NULL) { -+ TRACE_RECV_BOT("RX data for cmd %p " -+ "(sg_cnt %d, sg %p, sg[0].page %p)", -+ cmd, cmd->tgt_sg_cnt, sg, -+ (void *)sg_page(&sg[0])); -+ for (i = 0, j = 0; i < cmd->tgt_sg_cnt; ++i, ++j) { -+ if (unlikely(sg_is_chain(&sg[j]))) { -+ sg = sg_chain_ptr(&sg[j]); -+ j = 0; -+ } -+ PRINT_BUFF_FLAG(TRACE_RCV_BOT, "RX sg", -+ sg_virt(&sg[j]), sg[j].length); -+ } -+ } -+ } -+#endif -+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC; -+ -+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ -+ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED) -+ break; -+#endif -+ -+ /* Small context optimization */ -+ if ((pref_context == SCST_CONTEXT_TASKLET) || -+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) || -+ ((pref_context == SCST_CONTEXT_SAME) && -+ scst_cmd_atomic(cmd))) -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ -+ case SCST_RX_STATUS_ERROR_SENSE_SET: -+ scst_set_cmd_abnormal_done_state(cmd); -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ -+ case SCST_RX_STATUS_ERROR_FATAL: -+ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags); -+ /* go through */ -+ case SCST_RX_STATUS_ERROR: -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ -+ default: -+ PRINT_ERROR("scst_rx_data() received unknown status %x", -+ status); -+ scst_set_cmd_abnormal_done_state(cmd); -+ pref_context = SCST_CONTEXT_THREAD; -+ break; -+ } -+ -+ scst_process_redirect_cmd(cmd, pref_context, 1); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL(scst_rx_data); -+ -+static int scst_tgt_pre_exec(struct scst_cmd *cmd) -+{ -+ int res = SCST_CMD_STATE_RES_CONT_SAME, rc; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(cmd->resid_possible)) { -+ if (cmd->data_direction & SCST_DATA_WRITE) { -+ bool do_zero = false; -+ if (cmd->data_direction & SCST_DATA_READ) { -+ if (cmd->write_len != cmd->out_bufflen) -+ do_zero = true; -+ } else { -+ if (cmd->write_len != cmd->bufflen) -+ do_zero = true; -+ } -+ if (do_zero) { -+ scst_check_restore_sg_buff(cmd); -+ scst_zero_write_rest(cmd); -+ } -+ } -+ } -+ -+ cmd->state = SCST_CMD_STATE_SEND_FOR_EXEC; -+ -+ if ((cmd->tgtt->pre_exec == NULL) || unlikely(cmd->internal)) -+ goto out; -+ -+ TRACE_DBG("Calling pre_exec(%p)", cmd); -+ scst_set_cur_start(cmd); -+ rc = cmd->tgtt->pre_exec(cmd); -+ scst_set_pre_exec_time(cmd); -+ TRACE_DBG("pre_exec() returned %d", rc); -+ -+ if (unlikely(rc != SCST_PREPROCESS_STATUS_SUCCESS)) { -+ switch (rc) { -+ case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET: -+ scst_set_cmd_abnormal_done_state(cmd); -+ break; -+ case SCST_PREPROCESS_STATUS_ERROR_FATAL: -+ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags); -+ /* go through */ -+ case SCST_PREPROCESS_STATUS_ERROR: -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static void scst_do_cmd_done(struct scst_cmd *cmd, int result, -+ const uint8_t *rq_sense, int rq_sense_len, int resid) -+{ -+ TRACE_ENTRY(); -+ -+ scst_set_exec_time(cmd); -+ -+ cmd->status = result & 0xff; -+ cmd->msg_status = msg_byte(result); -+ cmd->host_status = host_byte(result); -+ cmd->driver_status = driver_byte(result); -+ if (unlikely(resid != 0)) { -+ if ((cmd->data_direction & SCST_DATA_READ) && -+ (resid > 0) && (resid < cmd->resp_data_len)) -+ scst_set_resp_data_len(cmd, cmd->resp_data_len - resid); -+ /* -+ * We ignore write direction residue, because from the -+ * initiator's POV we already transferred all the data. -+ */ -+ } -+ -+ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION)) { -+ /* We might have double reset UA here */ -+ cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len; -+ cmd->dbl_ua_orig_data_direction = cmd->data_direction; -+ -+ scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len); -+ } -+ -+ TRACE(TRACE_SCSI, "cmd %p, result %x, cmd->status %x, resid %d, " -+ "cmd->msg_status %x, cmd->host_status %x, " -+ "cmd->driver_status %x", cmd, result, cmd->status, resid, -+ cmd->msg_status, cmd->host_status, cmd->driver_status); -+ -+ cmd->completed = 1; -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* For small context optimization */ -+static inline enum scst_exec_context scst_optimize_post_exec_context( -+ struct scst_cmd *cmd, enum scst_exec_context context) -+{ -+ if (((context == SCST_CONTEXT_SAME) && scst_cmd_atomic(cmd)) || -+ (context == SCST_CONTEXT_TASKLET) || -+ (context == SCST_CONTEXT_DIRECT_ATOMIC)) { -+ if (!test_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC, -+ &cmd->tgt_dev->tgt_dev_flags)) -+ context = SCST_CONTEXT_THREAD; -+ } -+ return context; -+} -+ -+/** -+ * scst_pass_through_cmd_done - done callback for pass-through commands -+ * @data: private opaque data -+ * @sense: pointer to the sense data, if any -+ * @result: command's execution result -+ * @resid: residual, if any -+ */ -+void scst_pass_through_cmd_done(void *data, char *sense, int result, int resid) -+{ -+ struct scst_cmd *cmd; -+ -+ TRACE_ENTRY(); -+ -+ cmd = (struct scst_cmd *)data; -+ if (cmd == NULL) -+ goto out; -+ -+ scst_do_cmd_done(cmd, result, sense, SCSI_SENSE_BUFFERSIZE, resid); -+ -+ cmd->state = SCST_CMD_STATE_PRE_DEV_DONE; -+ -+ scst_process_redirect_cmd(cmd, -+ scst_optimize_post_exec_context(cmd, scst_estimate_context()), 0); -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_pass_through_cmd_done); -+ -+static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state, -+ enum scst_exec_context pref_context) -+{ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(cmd->pr_abort_counter != NULL); -+ -+ scst_set_exec_time(cmd); -+ -+ TRACE(TRACE_SCSI, "cmd %p, status %x, msg_status %x, host_status %x, " -+ "driver_status %x, resp_data_len %d", cmd, cmd->status, -+ cmd->msg_status, cmd->host_status, cmd->driver_status, -+ cmd->resp_data_len); -+ -+ if (next_state == SCST_CMD_STATE_DEFAULT) -+ next_state = SCST_CMD_STATE_PRE_DEV_DONE; -+ -+#if defined(CONFIG_SCST_DEBUG) -+ if (next_state == SCST_CMD_STATE_PRE_DEV_DONE) { -+ if ((trace_flag & TRACE_RCV_TOP) && (cmd->sg != NULL)) { -+ int i, j; -+ struct scatterlist *sg = cmd->sg; -+ TRACE_RECV_TOP("Exec'd %d S/G(s) at %p sg[0].page at " -+ "%p", cmd->sg_cnt, sg, (void *)sg_page(&sg[0])); -+ for (i = 0, j = 0; i < cmd->sg_cnt; ++i, ++j) { -+ if (unlikely(sg_is_chain(&sg[j]))) { -+ sg = sg_chain_ptr(&sg[j]); -+ j = 0; -+ } -+ TRACE_BUFF_FLAG(TRACE_RCV_TOP, -+ "Exec'd sg", sg_virt(&sg[j]), -+ sg[j].length); -+ } -+ } -+ } -+#endif -+ -+ cmd->state = next_state; -+ -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if ((next_state != SCST_CMD_STATE_PRE_DEV_DONE) && -+ (next_state != SCST_CMD_STATE_PRE_XMIT_RESP) && -+ (next_state != SCST_CMD_STATE_FINISHED) && -+ (next_state != SCST_CMD_STATE_FINISHED_INTERNAL)) { -+ PRINT_ERROR("%s() received invalid cmd state %d (opcode %d)", -+ __func__, next_state, cmd->cdb[0]); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ } -+#endif -+ pref_context = scst_optimize_post_exec_context(cmd, pref_context); -+ scst_process_redirect_cmd(cmd, pref_context, 0); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static int scst_report_luns_local(struct scst_cmd *cmd) -+{ -+ int res = SCST_EXEC_COMPLETED, rc; -+ int dev_cnt = 0; -+ int buffer_size; -+ int i; -+ struct scst_tgt_dev *tgt_dev = NULL; -+ uint8_t *buffer; -+ int offs, overflow = 0; -+ -+ TRACE_ENTRY(); -+ -+ rc = scst_check_local_events(cmd); -+ if (unlikely(rc != 0)) -+ goto out_done; -+ -+ cmd->status = 0; -+ cmd->msg_status = 0; -+ cmd->host_status = DID_OK; -+ cmd->driver_status = 0; -+ -+ if ((cmd->cdb[2] != 0) && (cmd->cdb[2] != 2)) { -+ PRINT_ERROR("Unsupported SELECT REPORT value %x in REPORT " -+ "LUNS command", cmd->cdb[2]); -+ goto out_err; -+ } -+ -+ buffer_size = scst_get_buf_full(cmd, &buffer); -+ if (unlikely(buffer_size == 0)) -+ goto out_compl; -+ else if (unlikely(buffer_size < 0)) -+ goto out_hw_err; -+ -+ if (buffer_size < 16) -+ goto out_put_err; -+ -+ memset(buffer, 0, buffer_size); -+ offs = 8; -+ -+ /* -+ * cmd won't allow to suspend activities, so we can access -+ * sess->sess_tgt_dev_list without any additional protection. -+ */ -+ for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { -+ struct list_head *head = &cmd->sess->sess_tgt_dev_list[i]; -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ if (!overflow) { -+ if ((buffer_size - offs) < 8) { -+ overflow = 1; -+ goto inc_dev_cnt; -+ } -+ *(__force __be64 *)&buffer[offs] -+ = scst_pack_lun(tgt_dev->lun, -+ cmd->sess->acg->addr_method); -+ offs += 8; -+ } -+inc_dev_cnt: -+ dev_cnt++; -+ } -+ } -+ -+ /* Set the response header */ -+ dev_cnt *= 8; -+ buffer[0] = (dev_cnt >> 24) & 0xff; -+ buffer[1] = (dev_cnt >> 16) & 0xff; -+ buffer[2] = (dev_cnt >> 8) & 0xff; -+ buffer[3] = dev_cnt & 0xff; -+ -+ scst_put_buf_full(cmd, buffer); -+ -+ dev_cnt += 8; -+ if (dev_cnt < cmd->resp_data_len) -+ scst_set_resp_data_len(cmd, dev_cnt); -+ -+out_compl: -+ cmd->completed = 1; -+ -+ /* Clear left sense_reported_luns_data_changed UA, if any. */ -+ -+ /* -+ * cmd won't allow to suspend activities, so we can access -+ * sess->sess_tgt_dev_list without any additional protection. -+ */ -+ for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { -+ struct list_head *head = &cmd->sess->sess_tgt_dev_list[i]; -+ -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ struct scst_tgt_dev_UA *ua; -+ -+ spin_lock_bh(&tgt_dev->tgt_dev_lock); -+ list_for_each_entry(ua, &tgt_dev->UA_list, -+ UA_list_entry) { -+ if (scst_analyze_sense(ua->UA_sense_buffer, -+ ua->UA_valid_sense_len, -+ SCST_SENSE_ALL_VALID, -+ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) { -+ TRACE_MGMT_DBG("Freeing not needed " -+ "REPORTED LUNS DATA CHANGED UA " -+ "%p", ua); -+ scst_tgt_dev_del_free_UA(tgt_dev, ua); -+ break; -+ } -+ } -+ spin_unlock_bh(&tgt_dev->tgt_dev_lock); -+ } -+ } -+ -+out_done: -+ /* Report the result */ -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_put_err: -+ scst_put_buf_full(cmd, buffer); -+ -+out_err: -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_compl; -+ -+out_hw_err: -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ goto out_compl; -+} -+ -+static int scst_request_sense_local(struct scst_cmd *cmd) -+{ -+ int res = SCST_EXEC_COMPLETED, rc; -+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; -+ uint8_t *buffer; -+ int buffer_size = 0, sl = 0; -+ -+ TRACE_ENTRY(); -+ -+ rc = scst_check_local_events(cmd); -+ if (unlikely(rc != 0)) -+ goto out_done; -+ -+ cmd->status = 0; -+ cmd->msg_status = 0; -+ cmd->host_status = DID_OK; -+ cmd->driver_status = 0; -+ -+ spin_lock_bh(&tgt_dev->tgt_dev_lock); -+ -+ if (tgt_dev->tgt_dev_valid_sense_len == 0) -+ goto out_unlock_not_completed; -+ -+ TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name); -+ -+ buffer_size = scst_get_buf_full(cmd, &buffer); -+ if (unlikely(buffer_size == 0)) -+ goto out_unlock_compl; -+ else if (unlikely(buffer_size < 0)) -+ goto out_unlock_hw_err; -+ -+ memset(buffer, 0, buffer_size); -+ -+ if (((tgt_dev->tgt_dev_sense[0] == 0x70) || -+ (tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) { -+ PRINT_WARNING("%s: Fixed format of the saved sense, but " -+ "descriptor format requested. Conversion will " -+ "truncated data", cmd->op_name); -+ PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense, -+ tgt_dev->tgt_dev_valid_sense_len); -+ -+ buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size); -+ sl = scst_set_sense(buffer, buffer_size, true, -+ tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12], -+ tgt_dev->tgt_dev_sense[13]); -+ } else if (((tgt_dev->tgt_dev_sense[0] == 0x72) || -+ (tgt_dev->tgt_dev_sense[0] == 0x73)) && !(cmd->cdb[1] & 1)) { -+ PRINT_WARNING("%s: Descriptor format of the " -+ "saved sense, but fixed format requested. Conversion " -+ "will truncated data", cmd->op_name); -+ PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense, -+ tgt_dev->tgt_dev_valid_sense_len); -+ -+ buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size); -+ sl = scst_set_sense(buffer, buffer_size, false, -+ tgt_dev->tgt_dev_sense[1], tgt_dev->tgt_dev_sense[2], -+ tgt_dev->tgt_dev_sense[3]); -+ } else { -+ if (buffer_size >= tgt_dev->tgt_dev_valid_sense_len) -+ sl = tgt_dev->tgt_dev_valid_sense_len; -+ else { -+ sl = buffer_size; -+ TRACE(TRACE_MINOR, "%s: Being returned sense truncated " -+ "to size %d (needed %d)", cmd->op_name, -+ buffer_size, tgt_dev->tgt_dev_valid_sense_len); -+ } -+ memcpy(buffer, tgt_dev->tgt_dev_sense, sl); -+ } -+ -+ scst_put_buf_full(cmd, buffer); -+ -+ tgt_dev->tgt_dev_valid_sense_len = 0; -+ -+ spin_unlock_bh(&tgt_dev->tgt_dev_lock); -+ -+ scst_set_resp_data_len(cmd, sl); -+ -+out_compl: -+ cmd->completed = 1; -+ -+out_done: -+ /* Report the result */ -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_unlock_hw_err: -+ spin_unlock_bh(&tgt_dev->tgt_dev_lock); -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ goto out_compl; -+ -+out_unlock_not_completed: -+ spin_unlock_bh(&tgt_dev->tgt_dev_lock); -+ res = SCST_EXEC_NOT_COMPLETED; -+ goto out; -+ -+out_unlock_compl: -+ spin_unlock_bh(&tgt_dev->tgt_dev_lock); -+ goto out_compl; -+} -+ -+static int scst_reserve_local(struct scst_cmd *cmd) -+{ -+ int res = SCST_EXEC_NOT_COMPLETED, rc; -+ struct scst_device *dev; -+ struct scst_tgt_dev *tgt_dev_tmp; -+ -+ TRACE_ENTRY(); -+ -+ if ((cmd->cdb[0] == RESERVE_10) && (cmd->cdb[2] & SCST_RES_3RDPTY)) { -+ PRINT_ERROR("RESERVE_10: 3rdPty RESERVE not implemented " -+ "(lun=%lld)", (long long unsigned int)cmd->lun); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_done; -+ } -+ -+ dev = cmd->dev; -+ -+ /* -+ * There's no need to block this device, even for -+ * SCST_CONTR_MODE_ONE_TASK_SET, or anyhow else protect reservations -+ * changes, because: -+ * -+ * 1. The reservation changes are (rather) atomic, i.e., in contrast -+ * to persistent reservations, don't have any invalid intermediate -+ * states during being changed. -+ * -+ * 2. It's a duty of initiators to ensure order of regular commands -+ * around the reservation command either by ORDERED attribute, or by -+ * queue draining, or etc. For case of SCST_CONTR_MODE_ONE_TASK_SET -+ * there are no target drivers which can ensure even for ORDERED -+ * commands order of their delivery, so, because initiators know -+ * it, also there's no point to do any extra protection actions. -+ */ -+ -+ rc = scst_pre_check_local_events(cmd); -+ if (unlikely(rc != 0)) -+ goto out_done; -+ -+ if (!list_empty(&dev->dev_registrants_list)) { -+ if (scst_pr_crh_case(cmd)) -+ goto out_completed; -+ else { -+ scst_set_cmd_error_status(cmd, -+ SAM_STAT_RESERVATION_CONFLICT); -+ goto out_done; -+ } -+ } -+ -+ spin_lock_bh(&dev->dev_lock); -+ -+ if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) { -+ spin_unlock_bh(&dev->dev_lock); -+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT); -+ goto out_done; -+ } -+ -+ list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ if (cmd->tgt_dev != tgt_dev_tmp) -+ set_bit(SCST_TGT_DEV_RESERVED, -+ &tgt_dev_tmp->tgt_dev_flags); -+ } -+ dev->dev_reserved = 1; -+ -+ spin_unlock_bh(&dev->dev_lock); -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_completed: -+ cmd->completed = 1; -+ -+out_done: -+ /* Report the result */ -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ res = SCST_EXEC_COMPLETED; -+ goto out; -+} -+ -+static int scst_release_local(struct scst_cmd *cmd) -+{ -+ int res = SCST_EXEC_NOT_COMPLETED, rc; -+ struct scst_tgt_dev *tgt_dev_tmp; -+ struct scst_device *dev; -+ -+ TRACE_ENTRY(); -+ -+ dev = cmd->dev; -+ -+ /* -+ * See comment in scst_reserve_local() why no dev blocking or any -+ * other protection is needed here. -+ */ -+ -+ rc = scst_pre_check_local_events(cmd); -+ if (unlikely(rc != 0)) -+ goto out_done; -+ -+ if (!list_empty(&dev->dev_registrants_list)) { -+ if (scst_pr_crh_case(cmd)) -+ goto out_completed; -+ else { -+ scst_set_cmd_error_status(cmd, -+ SAM_STAT_RESERVATION_CONFLICT); -+ goto out_done; -+ } -+ } -+ -+ spin_lock_bh(&dev->dev_lock); -+ -+ /* -+ * The device could be RELEASED behind us, if RESERVING session -+ * is closed (see scst_free_tgt_dev()), but this actually doesn't -+ * matter, so use lock and no retest for DEV_RESERVED bits again -+ */ -+ if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) { -+ res = SCST_EXEC_COMPLETED; -+ cmd->status = 0; -+ cmd->msg_status = 0; -+ cmd->host_status = DID_OK; -+ cmd->driver_status = 0; -+ cmd->completed = 1; -+ } else { -+ list_for_each_entry(tgt_dev_tmp, -+ &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ clear_bit(SCST_TGT_DEV_RESERVED, -+ &tgt_dev_tmp->tgt_dev_flags); -+ } -+ dev->dev_reserved = 0; -+ } -+ -+ spin_unlock_bh(&dev->dev_lock); -+ -+ if (res == SCST_EXEC_COMPLETED) -+ goto out_done; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_completed: -+ cmd->completed = 1; -+ -+out_done: -+ res = SCST_EXEC_COMPLETED; -+ /* Report the result */ -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ goto out; -+} -+ -+/* No locks, no IRQ or IRQ-disabled context allowed */ -+static int scst_persistent_reserve_in_local(struct scst_cmd *cmd) -+{ -+ int rc; -+ struct scst_device *dev; -+ struct scst_tgt_dev *tgt_dev; -+ struct scst_session *session; -+ int action; -+ uint8_t *buffer; -+ int buffer_size; -+ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(cmd)); -+ -+ dev = cmd->dev; -+ tgt_dev = cmd->tgt_dev; -+ session = cmd->sess; -+ -+ rc = scst_check_local_events(cmd); -+ if (unlikely(rc != 0)) -+ goto out_done; -+ -+ if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) { -+ PRINT_WARNING("Persistent Reservation command %x refused for " -+ "device %s, because the device has not supporting PR " -+ "transports connected", cmd->cdb[0], dev->virt_name); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); -+ goto out_done; -+ } -+ -+ if (dev->dev_reserved) { -+ TRACE_PR("PR command rejected, because device %s holds regular " -+ "reservation", dev->virt_name); -+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT); -+ goto out_done; -+ } -+ -+ if (dev->scsi_dev != NULL) { -+ PRINT_WARNING("PR commands for pass-through devices not " -+ "supported (device %s)", dev->virt_name); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); -+ goto out_done; -+ } -+ -+ buffer_size = scst_get_buf_full(cmd, &buffer); -+ if (unlikely(buffer_size <= 0)) { -+ if (buffer_size < 0) -+ scst_set_busy(cmd); -+ goto out_done; -+ } -+ -+ scst_pr_write_lock(dev); -+ -+ /* We can be aborted by another PR command while waiting for the lock */ -+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { -+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd); -+ goto out_unlock; -+ } -+ -+ action = cmd->cdb[1] & 0x1f; -+ -+ TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action, -+ dev->virt_name, tgt_dev->lun, session->initiator_name); -+ -+ switch (action) { -+ case PR_READ_KEYS: -+ scst_pr_read_keys(cmd, buffer, buffer_size); -+ break; -+ case PR_READ_RESERVATION: -+ scst_pr_read_reservation(cmd, buffer, buffer_size); -+ break; -+ case PR_REPORT_CAPS: -+ scst_pr_report_caps(cmd, buffer, buffer_size); -+ break; -+ case PR_READ_FULL_STATUS: -+ scst_pr_read_full_status(cmd, buffer, buffer_size); -+ break; -+ default: -+ PRINT_ERROR("Unsupported action %x", action); -+ scst_pr_write_unlock(dev); -+ goto out_err; -+ } -+ -+out_complete: -+ cmd->completed = 1; -+ -+out_unlock: -+ scst_pr_write_unlock(dev); -+ -+ scst_put_buf_full(cmd, buffer); -+ -+out_done: -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ -+ TRACE_EXIT_RES(SCST_EXEC_COMPLETED); -+ return SCST_EXEC_COMPLETED; -+ -+out_err: -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_complete; -+} -+ -+/* No locks, no IRQ or IRQ-disabled context allowed */ -+static int scst_persistent_reserve_out_local(struct scst_cmd *cmd) -+{ -+ int res = SCST_EXEC_COMPLETED; -+ int rc; -+ struct scst_device *dev; -+ struct scst_tgt_dev *tgt_dev; -+ struct scst_session *session; -+ int action; -+ uint8_t *buffer; -+ int buffer_size; -+ bool aborted = false; -+ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(cmd)); -+ -+ dev = cmd->dev; -+ tgt_dev = cmd->tgt_dev; -+ session = cmd->sess; -+ -+ rc = scst_check_local_events(cmd); -+ if (unlikely(rc != 0)) -+ goto out_done; -+ -+ if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) { -+ PRINT_WARNING("Persistent Reservation command %x refused for " -+ "device %s, because the device has not supporting PR " -+ "transports connected", cmd->cdb[0], dev->virt_name); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); -+ goto out_done; -+ } -+ -+ action = cmd->cdb[1] & 0x1f; -+ -+ TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action, -+ dev->virt_name, tgt_dev->lun, session->initiator_name); -+ -+ if (dev->dev_reserved) { -+ TRACE_PR("PR command rejected, because device %s holds regular " -+ "reservation", dev->virt_name); -+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT); -+ goto out_done; -+ } -+ -+ /* -+ * Check if tgt_dev already registered. Also by this check we make -+ * sure that table "PERSISTENT RESERVE OUT service actions that are -+ * allowed in the presence of various reservations" is honored. -+ * REGISTER AND MOVE and RESERVE will be additionally checked for -+ * conflicts later. -+ */ -+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) && -+ (tgt_dev->registrant == NULL)) { -+ TRACE_PR("'%s' not registered", cmd->sess->initiator_name); -+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT); -+ goto out_done; -+ } -+ -+ buffer_size = scst_get_buf_full(cmd, &buffer); -+ if (unlikely(buffer_size <= 0)) { -+ if (buffer_size < 0) -+ scst_set_busy(cmd); -+ goto out_done; -+ } -+ -+ /* Check scope */ -+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) && -+ (action != PR_CLEAR) && ((cmd->cdb[2] & 0x0f) >> 4) != SCOPE_LU) { -+ TRACE_PR("Scope must be SCOPE_LU for action %x", action); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_put_buf_full; -+ } -+ -+ /* Check SPEC_I_PT (PR_REGISTER_AND_MOVE has another format) */ -+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_MOVE) && -+ ((buffer[20] >> 3) & 0x01)) { -+ TRACE_PR("SPEC_I_PT must be zero for action %x", action); -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE( -+ scst_sense_invalid_field_in_cdb)); -+ goto out_put_buf_full; -+ } -+ -+ /* Check ALL_TG_PT (PR_REGISTER_AND_MOVE has another format) */ -+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) && -+ (action != PR_REGISTER_AND_MOVE) && ((buffer[20] >> 2) & 0x01)) { -+ TRACE_PR("ALL_TG_PT must be zero for action %x", action); -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE( -+ scst_sense_invalid_field_in_cdb)); -+ goto out_put_buf_full; -+ } -+ -+ scst_pr_write_lock(dev); -+ -+ /* We can be aborted by another PR command while waiting for the lock */ -+ aborted = test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags); -+ if (unlikely(aborted)) { -+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd); -+ goto out_unlock; -+ } -+ -+ switch (action) { -+ case PR_REGISTER: -+ scst_pr_register(cmd, buffer, buffer_size); -+ break; -+ case PR_RESERVE: -+ scst_pr_reserve(cmd, buffer, buffer_size); -+ break; -+ case PR_RELEASE: -+ scst_pr_release(cmd, buffer, buffer_size); -+ break; -+ case PR_CLEAR: -+ scst_pr_clear(cmd, buffer, buffer_size); -+ break; -+ case PR_PREEMPT: -+ scst_pr_preempt(cmd, buffer, buffer_size); -+ break; -+ case PR_PREEMPT_AND_ABORT: -+ scst_pr_preempt_and_abort(cmd, buffer, buffer_size); -+ break; -+ case PR_REGISTER_AND_IGNORE: -+ scst_pr_register_and_ignore(cmd, buffer, buffer_size); -+ break; -+ case PR_REGISTER_AND_MOVE: -+ scst_pr_register_and_move(cmd, buffer, buffer_size); -+ break; -+ default: -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); -+ goto out_unlock; -+ } -+ -+ if (cmd->status == SAM_STAT_GOOD) -+ scst_pr_sync_device_file(tgt_dev, cmd); -+ -+ if ((dev->handler->pr_cmds_notifications) && -+ (cmd->status == SAM_STAT_GOOD)) /* sync file may change status */ -+ res = SCST_EXEC_NOT_COMPLETED; -+ -+out_unlock: -+ scst_pr_write_unlock(dev); -+ -+out_put_buf_full: -+ scst_put_buf_full(cmd, buffer); -+ -+out_done: -+ if (SCST_EXEC_COMPLETED == res) { -+ if (!aborted) -+ cmd->completed = 1; -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, -+ SCST_CONTEXT_SAME); -+ } -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/** -+ * scst_check_local_events() - check if there are any local SCSI events -+ * -+ * Description: -+ * Checks if the command can be executed or there are local events, -+ * like reservations, pending UAs, etc. Returns < 0 if command must be -+ * aborted, > 0 if there is an event and command should be immediately -+ * completed, or 0 otherwise. -+ * -+ * !! 1.Dev handlers implementing exec() callback must call this function there -+ * !! just before the actual command's execution! -+ * !! -+ * !! 2. If this function can be called more than once on the processing path -+ * !! scst_pre_check_local_events() should be used for the first call! -+ * -+ * On call no locks, no IRQ or IRQ-disabled context allowed. -+ */ -+int scst_check_local_events(struct scst_cmd *cmd) -+{ -+ int res, rc; -+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; -+ struct scst_device *dev = cmd->dev; -+ -+ TRACE_ENTRY(); -+ -+ /* -+ * There's no race here, because we need to trace commands sent -+ * *after* dev_double_ua_possible flag was set. -+ */ -+ if (unlikely(dev->dev_double_ua_possible)) -+ cmd->double_ua_possible = 1; -+ -+ /* Reserve check before Unit Attention */ -+ if (unlikely(test_bit(SCST_TGT_DEV_RESERVED, -+ &tgt_dev->tgt_dev_flags))) { -+ if ((cmd->op_flags & SCST_REG_RESERVE_ALLOWED) == 0) { -+ scst_set_cmd_error_status(cmd, -+ SAM_STAT_RESERVATION_CONFLICT); -+ goto out_dec_pr_readers_count; -+ } -+ } -+ -+ if (likely(!cmd->check_local_events_once_done)) { -+ if (dev->pr_is_set) { -+ if (unlikely(!scst_pr_is_cmd_allowed(cmd))) { -+ scst_set_cmd_error_status(cmd, -+ SAM_STAT_RESERVATION_CONFLICT); -+ goto out_complete; -+ } -+ } else -+ scst_dec_pr_readers_count(cmd, false); -+ } -+ -+ /* -+ * Let's check for ABORTED after scst_pr_is_cmd_allowed(), because -+ * we might sleep for a while there. -+ */ -+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { -+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd); -+ goto out_uncomplete; -+ } -+ -+ /* If we had internal bus reset, set the command error unit attention */ -+ if ((dev->scsi_dev != NULL) && -+ unlikely(dev->scsi_dev->was_reset)) { -+ if (scst_is_ua_command(cmd)) { -+ int done = 0; -+ /* -+ * Prevent more than 1 cmd to be triggered by was_reset -+ */ -+ spin_lock_bh(&dev->dev_lock); -+ if (dev->scsi_dev->was_reset) { -+ TRACE(TRACE_MGMT, "was_reset is %d", 1); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_reset_UA)); -+ /* -+ * It looks like it is safe to clear was_reset -+ * here -+ */ -+ dev->scsi_dev->was_reset = 0; -+ done = 1; -+ } -+ spin_unlock_bh(&dev->dev_lock); -+ -+ if (done) -+ goto out_complete; -+ } -+ } -+ -+ if (unlikely(test_bit(SCST_TGT_DEV_UA_PENDING, -+ &cmd->tgt_dev->tgt_dev_flags))) { -+ if (scst_is_ua_command(cmd)) { -+ rc = scst_set_pending_UA(cmd); -+ if (rc == 0) -+ goto out_complete; -+ } -+ } -+ -+ res = 0; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_dec_pr_readers_count: -+ if (cmd->dec_pr_readers_count_needed) -+ scst_dec_pr_readers_count(cmd, false); -+ -+out_complete: -+ res = 1; -+ BUG_ON(!cmd->completed); -+ goto out; -+ -+out_uncomplete: -+ res = -1; -+ goto out; -+} -+EXPORT_SYMBOL_GPL(scst_check_local_events); -+ -+/* No locks */ -+void scst_inc_expected_sn(struct scst_order_data *order_data, atomic_t *slot) -+{ -+ if (slot == NULL) -+ goto inc; -+ -+ /* Optimized for lockless fast path */ -+ -+ TRACE_SN("Slot %zd, *cur_sn_slot %d", slot - order_data->sn_slots, -+ atomic_read(slot)); -+ -+ if (!atomic_dec_and_test(slot)) -+ goto out; -+ -+ TRACE_SN("Slot is 0 (num_free_sn_slots=%d)", -+ order_data->num_free_sn_slots); -+ if (order_data->num_free_sn_slots < (int)ARRAY_SIZE(order_data->sn_slots)-1) { -+ spin_lock_irq(&order_data->sn_lock); -+ if (likely(order_data->num_free_sn_slots < (int)ARRAY_SIZE(order_data->sn_slots)-1)) { -+ if (order_data->num_free_sn_slots < 0) -+ order_data->cur_sn_slot = slot; -+ /* To be in-sync with SIMPLE case in scst_cmd_set_sn() */ -+ smp_mb(); -+ order_data->num_free_sn_slots++; -+ TRACE_SN("Incremented num_free_sn_slots (%d)", -+ order_data->num_free_sn_slots); -+ -+ } -+ spin_unlock_irq(&order_data->sn_lock); -+ } -+ -+inc: -+ /* -+ * No protection of expected_sn is needed, because only one thread -+ * at time can be here (serialized by sn). Also it is supposed that -+ * there could not be half-incremented halves. -+ */ -+ order_data->expected_sn++; -+ /* -+ * Write must be before def_cmd_count read to be in sync. with -+ * scst_post_exec_sn(). See comment in scst_send_for_exec(). -+ */ -+ smp_mb(); -+ TRACE_SN("Next expected_sn: %d", order_data->expected_sn); -+ -+out: -+ return; -+} -+ -+/* No locks */ -+static struct scst_cmd *scst_post_exec_sn(struct scst_cmd *cmd, -+ bool make_active) -+{ -+ /* For HQ commands SN is not set */ -+ bool inc_expected_sn = !cmd->inc_expected_sn_on_done && -+ cmd->sn_set && !cmd->retry; -+ struct scst_order_data *order_data = cmd->cur_order_data; -+ struct scst_cmd *res; -+ -+ TRACE_ENTRY(); -+ -+ if (inc_expected_sn) -+ scst_inc_expected_sn(order_data, cmd->sn_slot); -+ -+ if (make_active) { -+ scst_make_deferred_commands_active(order_data); -+ res = NULL; -+ } else -+ res = scst_check_deferred_commands(order_data); -+ -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/* cmd must be additionally referenced to not die inside */ -+static int scst_do_real_exec(struct scst_cmd *cmd) -+{ -+ int res = SCST_EXEC_NOT_COMPLETED; -+ int rc; -+ struct scst_device *dev = cmd->dev; -+ struct scst_dev_type *handler = dev->handler; -+ struct io_context *old_ctx = NULL; -+ bool ctx_changed = false; -+ struct scsi_device *scsi_dev; -+ -+ TRACE_ENTRY(); -+ -+ ctx_changed = scst_set_io_context(cmd, &old_ctx); -+ -+ cmd->state = SCST_CMD_STATE_REAL_EXECUTING; -+ -+ if (handler->exec) { -+ TRACE_DBG("Calling dev handler %s exec(%p)", -+ handler->name, cmd); -+ TRACE_BUFF_FLAG(TRACE_SND_TOP, "Execing: ", cmd->cdb, -+ cmd->cdb_len); -+ scst_set_cur_start(cmd); -+ res = handler->exec(cmd); -+ TRACE_DBG("Dev handler %s exec() returned %d", -+ handler->name, res); -+ -+ if (res == SCST_EXEC_COMPLETED) -+ goto out_complete; -+ -+ scst_set_exec_time(cmd); -+ -+ BUG_ON(res != SCST_EXEC_NOT_COMPLETED); -+ } -+ -+ TRACE_DBG("Sending cmd %p to SCSI mid-level", cmd); -+ -+ scsi_dev = dev->scsi_dev; -+ -+ if (unlikely(scsi_dev == NULL)) { -+ PRINT_ERROR("Command for virtual device must be " -+ "processed by device handler (LUN %lld)!", -+ (long long unsigned int)cmd->lun); -+ goto out_error; -+ } -+ -+ res = scst_check_local_events(cmd); -+ if (unlikely(res != 0)) -+ goto out_done; -+ -+ scst_set_cur_start(cmd); -+ -+ rc = scst_scsi_exec_async(cmd, cmd, scst_pass_through_cmd_done); -+ if (unlikely(rc != 0)) { -+ PRINT_ERROR("scst pass-through exec failed: %x", rc); -+ if (((int)rc == -EINVAL) && -+ (cmd->bufflen > queue_max_hw_sectors(scsi_dev->request_queue))) -+ PRINT_ERROR("Too low max_hw_sectors %d sectors on %s " -+ "to serve command %x with bufflen %db." -+ "See README for more details.", -+ queue_max_hw_sectors(scsi_dev->request_queue), -+ dev->virt_name, cmd->cdb[0], cmd->bufflen); -+ goto out_error; -+ } -+ -+out_complete: -+ res = SCST_EXEC_COMPLETED; -+ -+ if (ctx_changed) -+ scst_reset_io_context(cmd->tgt_dev, old_ctx); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_error: -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ goto out_done; -+ -+out_done: -+ res = SCST_EXEC_COMPLETED; -+ /* Report the result */ -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ goto out_complete; -+} -+ -+static inline int scst_real_exec(struct scst_cmd *cmd) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_SAME != SCST_EXEC_NOT_COMPLETED); -+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_NEXT != SCST_EXEC_COMPLETED); -+ -+ __scst_cmd_get(cmd); -+ -+ res = scst_do_real_exec(cmd); -+ if (likely(res == SCST_EXEC_COMPLETED)) { -+ scst_post_exec_sn(cmd, true); -+ } else -+ BUG(); -+ -+ __scst_cmd_put(cmd); -+ -+ /* SCST_EXEC_* match SCST_CMD_STATE_RES_* */ -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_do_local_exec(struct scst_cmd *cmd) -+{ -+ int res; -+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; -+ -+ TRACE_ENTRY(); -+ -+ /* Check READ_ONLY device status */ -+ if ((cmd->op_flags & SCST_WRITE_MEDIUM) && -+ (tgt_dev->acg_dev->rd_only || cmd->dev->swp || -+ cmd->dev->rd_only)) { -+ PRINT_WARNING("Attempt of write access to read-only device: " -+ "initiator %s, LUN %lld, op %x", -+ cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_data_protect)); -+ goto out_done; -+ } -+ -+ if (!scst_is_cmd_local(cmd)) { -+ res = SCST_EXEC_NOT_COMPLETED; -+ goto out; -+ } -+ -+ switch (cmd->cdb[0]) { -+ case RESERVE: -+ case RESERVE_10: -+ res = scst_reserve_local(cmd); -+ break; -+ case RELEASE: -+ case RELEASE_10: -+ res = scst_release_local(cmd); -+ break; -+ case PERSISTENT_RESERVE_IN: -+ res = scst_persistent_reserve_in_local(cmd); -+ break; -+ case PERSISTENT_RESERVE_OUT: -+ res = scst_persistent_reserve_out_local(cmd); -+ break; -+ case REPORT_LUNS: -+ res = scst_report_luns_local(cmd); -+ break; -+ case REQUEST_SENSE: -+ res = scst_request_sense_local(cmd); -+ break; -+ default: -+ res = SCST_EXEC_NOT_COMPLETED; -+ break; -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_done: -+ /* Report the result */ -+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); -+ res = SCST_EXEC_COMPLETED; -+ goto out; -+} -+ -+static int scst_local_exec(struct scst_cmd *cmd) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_SAME != SCST_EXEC_NOT_COMPLETED); -+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_NEXT != SCST_EXEC_COMPLETED); -+ -+ __scst_cmd_get(cmd); -+ -+ res = scst_do_local_exec(cmd); -+ if (likely(res == SCST_EXEC_NOT_COMPLETED)) -+ cmd->state = SCST_CMD_STATE_REAL_EXEC; -+ else if (res == SCST_EXEC_COMPLETED) -+ scst_post_exec_sn(cmd, true); -+ else -+ BUG(); -+ -+ __scst_cmd_put(cmd); -+ -+ /* SCST_EXEC_* match SCST_CMD_STATE_RES_* */ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_exec(struct scst_cmd **active_cmd) -+{ -+ struct scst_cmd *cmd = *active_cmd; -+ struct scst_cmd *ref_cmd; -+ int res = SCST_CMD_STATE_RES_CONT_NEXT, count = 0; -+ -+ TRACE_ENTRY(); -+ -+ cmd->state = SCST_CMD_STATE_START_EXEC; -+ -+ if (unlikely(scst_check_blocked_dev(cmd))) -+ goto out; -+ -+ /* To protect tgt_dev */ -+ ref_cmd = cmd; -+ __scst_cmd_get(ref_cmd); -+ -+ while (1) { -+ int rc; -+ -+ cmd->sent_for_exec = 1; -+ /* -+ * To sync with scst_abort_cmd(). The above assignment must -+ * be before SCST_CMD_ABORTED test, done later in -+ * scst_check_local_events(). It's far from here, so the order -+ * is virtually guaranteed, but let's have it just in case. -+ */ -+ smp_mb(); -+ -+ cmd->scst_cmd_done = scst_cmd_done_local; -+ cmd->state = SCST_CMD_STATE_LOCAL_EXEC; -+ -+ rc = scst_do_local_exec(cmd); -+ if (likely(rc == SCST_EXEC_NOT_COMPLETED)) -+ /* Nothing to do */; -+ else { -+ BUG_ON(rc != SCST_EXEC_COMPLETED); -+ goto done; -+ } -+ -+ cmd->state = SCST_CMD_STATE_REAL_EXEC; -+ -+ rc = scst_do_real_exec(cmd); -+ BUG_ON(rc != SCST_EXEC_COMPLETED); -+ -+done: -+ count++; -+ -+ cmd = scst_post_exec_sn(cmd, false); -+ if (cmd == NULL) -+ break; -+ -+ cmd->state = SCST_CMD_STATE_START_EXEC; -+ -+ if (unlikely(scst_check_blocked_dev(cmd))) -+ break; -+ -+ __scst_cmd_put(ref_cmd); -+ ref_cmd = cmd; -+ __scst_cmd_get(ref_cmd); -+ -+ } -+ -+ *active_cmd = cmd; -+ -+ if (count == 0) -+ goto out_put; -+ -+out_put: -+ __scst_cmd_put(ref_cmd); -+ /* !! At this point sess, dev and tgt_dev can be already freed !! */ -+ -+out: -+ EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD); -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_send_for_exec(struct scst_cmd **active_cmd) -+{ -+ int res; -+ struct scst_cmd *cmd = *active_cmd; -+ struct scst_order_data *order_data = cmd->cur_order_data; -+ typeof(order_data->expected_sn) expected_sn; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(cmd->internal)) -+ goto exec; -+ -+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE)) -+ goto exec; -+ -+ BUG_ON(!cmd->sn_set); -+ -+ expected_sn = order_data->expected_sn; -+ /* Optimized for lockless fast path */ -+ if ((cmd->sn != expected_sn) || (order_data->hq_cmd_count > 0)) { -+ spin_lock_irq(&order_data->sn_lock); -+ -+ order_data->def_cmd_count++; -+ /* -+ * Memory barrier is needed here to implement lockless fast -+ * path. We need the exact order of read and write between -+ * def_cmd_count and expected_sn. Otherwise, we can miss case, -+ * when expected_sn was changed to be equal to cmd->sn while -+ * we are queueing cmd the deferred list after the expected_sn -+ * below. It will lead to a forever stuck command. But with -+ * the barrier in such case __scst_check_deferred_commands() -+ * will be called and it will take sn_lock, so we will be -+ * synchronized. -+ */ -+ smp_mb(); -+ -+ expected_sn = order_data->expected_sn; -+ if ((cmd->sn != expected_sn) || (order_data->hq_cmd_count > 0)) { -+ if (unlikely(test_bit(SCST_CMD_ABORTED, -+ &cmd->cmd_flags))) { -+ /* Necessary to allow aborting out of sn cmds */ -+ TRACE_MGMT_DBG("Aborting out of sn cmd %p " -+ "(tag %llu, sn %u)", cmd, -+ (long long unsigned)cmd->tag, cmd->sn); -+ order_data->def_cmd_count--; -+ scst_set_cmd_abnormal_done_state(cmd); -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ } else { -+ TRACE_SN("Deferring cmd %p (sn=%d, set %d, " -+ "expected_sn=%d)", cmd, cmd->sn, -+ cmd->sn_set, expected_sn); -+ list_add_tail(&cmd->sn_cmd_list_entry, -+ &order_data->deferred_cmd_list); -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ } -+ spin_unlock_irq(&order_data->sn_lock); -+ goto out; -+ } else { -+ TRACE_SN("Somebody incremented expected_sn %d, " -+ "continuing", expected_sn); -+ order_data->def_cmd_count--; -+ spin_unlock_irq(&order_data->sn_lock); -+ } -+ } -+ -+exec: -+ res = scst_exec(active_cmd); -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/* No locks supposed to be held */ -+static int scst_check_sense(struct scst_cmd *cmd) -+{ -+ int res = 0; -+ struct scst_device *dev = cmd->dev; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(cmd->ua_ignore)) -+ goto out; -+ -+ /* If we had internal bus reset behind us, set the command error UA */ -+ if ((dev->scsi_dev != NULL) && -+ unlikely(cmd->host_status == DID_RESET) && -+ scst_is_ua_command(cmd)) { -+ TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x", -+ dev->scsi_dev->was_reset, cmd->host_status); -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA)); -+ /* It looks like it is safe to clear was_reset here */ -+ dev->scsi_dev->was_reset = 0; -+ } -+ -+ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) && -+ SCST_SENSE_VALID(cmd->sense)) { -+ PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense, -+ cmd->sense_valid_len); -+ -+ /* Check Unit Attention Sense Key */ -+ if (scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) { -+ if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len, -+ SCST_SENSE_ASC_VALID, -+ 0, SCST_SENSE_ASC_UA_RESET, 0)) { -+ if (cmd->double_ua_possible) { -+ TRACE_MGMT_DBG("Double UA " -+ "detected for device %p", dev); -+ TRACE_MGMT_DBG("Retrying cmd" -+ " %p (tag %llu)", cmd, -+ (long long unsigned)cmd->tag); -+ -+ cmd->status = 0; -+ cmd->msg_status = 0; -+ cmd->host_status = DID_OK; -+ cmd->driver_status = 0; -+ cmd->completed = 0; -+ -+ mempool_free(cmd->sense, -+ scst_sense_mempool); -+ cmd->sense = NULL; -+ -+ scst_check_restore_sg_buff(cmd); -+ -+ BUG_ON(cmd->dbl_ua_orig_resp_data_len < 0); -+ cmd->data_direction = -+ cmd->dbl_ua_orig_data_direction; -+ cmd->resp_data_len = -+ cmd->dbl_ua_orig_resp_data_len; -+ -+ cmd->state = SCST_CMD_STATE_REAL_EXEC; -+ cmd->retry = 1; -+ scst_reset_requeued_cmd(cmd); -+ res = 1; -+ goto out; -+ } -+ } -+ scst_dev_check_set_UA(dev, cmd, cmd->sense, -+ cmd->sense_valid_len); -+ } -+ } -+ -+ if (unlikely(cmd->double_ua_possible)) { -+ if (scst_is_ua_command(cmd)) { -+ TRACE_MGMT_DBG("Clearing dbl_ua_possible flag (dev %p, " -+ "cmd %p)", dev, cmd); -+ /* -+ * Lock used to protect other flags in the bitfield -+ * (just in case, actually). Those flags can't be -+ * changed in parallel, because the device is -+ * serialized. -+ */ -+ spin_lock_bh(&dev->dev_lock); -+ dev->dev_double_ua_possible = 0; -+ spin_unlock_bh(&dev->dev_lock); -+ } -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_check_auto_sense(struct scst_cmd *cmd) -+{ -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) && -+ (!SCST_SENSE_VALID(cmd->sense) || -+ SCST_NO_SENSE(cmd->sense))) { -+ TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "CHECK_CONDITION, " -+ "but no sense: cmd->status=%x, cmd->msg_status=%x, " -+ "cmd->host_status=%x, cmd->driver_status=%x (cmd %p)", -+ cmd->status, cmd->msg_status, cmd->host_status, -+ cmd->driver_status, cmd); -+ res = 1; -+ } else if (unlikely(cmd->host_status)) { -+ if ((cmd->host_status == DID_REQUEUE) || -+ (cmd->host_status == DID_IMM_RETRY) || -+ (cmd->host_status == DID_SOFT_ERROR) || -+ (cmd->host_status == DID_ABORT)) { -+ scst_set_busy(cmd); -+ } else { -+ TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "Host " -+ "status %x received, returning HARDWARE ERROR " -+ "instead (cmd %p)", cmd->host_status, cmd); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ } -+ } -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_pre_dev_done(struct scst_cmd *cmd) -+{ -+ int res = SCST_CMD_STATE_RES_CONT_SAME, rc; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(scst_check_auto_sense(cmd))) { -+ PRINT_INFO("Command finished with CHECK CONDITION, but " -+ "without sense data (opcode 0x%x), issuing " -+ "REQUEST SENSE", cmd->cdb[0]); -+ rc = scst_prepare_request_sense(cmd); -+ if (rc == 0) -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ else { -+ PRINT_ERROR("%s", "Unable to issue REQUEST SENSE, " -+ "returning HARDWARE ERROR"); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ } -+ goto out; -+ } else if (unlikely(scst_check_sense(cmd))) { -+ /* -+ * We can't allow atomic command on the exec stages, so -+ * restart to the thread -+ */ -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ if (likely(scsi_status_is_good(cmd->status))) { -+ unsigned char type = cmd->dev->type; -+ if (unlikely((cmd->cdb[0] == MODE_SENSE || -+ cmd->cdb[0] == MODE_SENSE_10)) && -+ (cmd->tgt_dev->acg_dev->rd_only || cmd->dev->swp || -+ cmd->dev->rd_only) && -+ (type == TYPE_DISK || -+ type == TYPE_WORM || -+ type == TYPE_MOD || -+ type == TYPE_TAPE)) { -+ int32_t length; -+ uint8_t *address; -+ bool err = false; -+ -+ length = scst_get_buf_full(cmd, &address); -+ if (length < 0) { -+ PRINT_ERROR("%s", "Unable to get " -+ "MODE_SENSE buffer"); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE( -+ scst_sense_hardw_error)); -+ err = true; -+ } else if (length > 2 && cmd->cdb[0] == MODE_SENSE) -+ address[2] |= 0x80; /* Write Protect*/ -+ else if (length > 3 && cmd->cdb[0] == MODE_SENSE_10) -+ address[3] |= 0x80; /* Write Protect*/ -+ scst_put_buf_full(cmd, address); -+ -+ if (err) -+ goto out; -+ } -+ -+ /* -+ * Check and clear NormACA option for the device, if necessary, -+ * since we don't support ACA -+ */ -+ if (unlikely((cmd->cdb[0] == INQUIRY)) && -+ /* Std INQUIRY data (no EVPD) */ -+ !(cmd->cdb[1] & SCST_INQ_EVPD) && -+ (cmd->resp_data_len > SCST_INQ_BYTE3)) { -+ uint8_t *buffer; -+ int buflen; -+ bool err = false; -+ -+ buflen = scst_get_buf_full(cmd, &buffer); -+ if (buflen > SCST_INQ_BYTE3 && !cmd->tgtt->fake_aca) { -+#ifdef CONFIG_SCST_EXTRACHECKS -+ if (buffer[SCST_INQ_BYTE3] & SCST_INQ_NORMACA_BIT) { -+ PRINT_INFO("NormACA set for device: " -+ "lun=%lld, type 0x%02x. Clear it, " -+ "since it's unsupported.", -+ (long long unsigned int)cmd->lun, -+ buffer[0]); -+ } -+#endif -+ buffer[SCST_INQ_BYTE3] &= ~SCST_INQ_NORMACA_BIT; -+ } else if (buflen <= SCST_INQ_BYTE3 && buflen != 0) { -+ PRINT_ERROR("%s", "Unable to get INQUIRY " -+ "buffer"); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ err = true; -+ } -+ if (buflen > 0) -+ scst_put_buf_full(cmd, buffer); -+ -+ if (err) -+ goto out; -+ } -+ -+ if (unlikely((cmd->cdb[0] == MODE_SELECT) || -+ (cmd->cdb[0] == MODE_SELECT_10) || -+ (cmd->cdb[0] == LOG_SELECT))) { -+ TRACE(TRACE_SCSI, -+ "MODE/LOG SELECT succeeded (LUN %lld)", -+ (long long unsigned int)cmd->lun); -+ cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS; -+ goto out; -+ } -+ } else { -+ TRACE(TRACE_SCSI, "cmd %p not succeeded with status %x", -+ cmd, cmd->status); -+ -+ if ((cmd->cdb[0] == RESERVE) || (cmd->cdb[0] == RESERVE_10)) { -+ if (!test_bit(SCST_TGT_DEV_RESERVED, -+ &cmd->tgt_dev->tgt_dev_flags)) { -+ struct scst_tgt_dev *tgt_dev_tmp; -+ struct scst_device *dev = cmd->dev; -+ -+ TRACE(TRACE_SCSI, "RESERVE failed lun=%lld, " -+ "status=%x", -+ (long long unsigned int)cmd->lun, -+ cmd->status); -+ PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense, -+ cmd->sense_valid_len); -+ -+ /* Clearing the reservation */ -+ spin_lock_bh(&dev->dev_lock); -+ list_for_each_entry(tgt_dev_tmp, -+ &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ clear_bit(SCST_TGT_DEV_RESERVED, -+ &tgt_dev_tmp->tgt_dev_flags); -+ } -+ dev->dev_reserved = 0; -+ spin_unlock_bh(&dev->dev_lock); -+ } -+ } -+ -+ /* Check for MODE PARAMETERS CHANGED UA */ -+ if ((cmd->dev->scsi_dev != NULL) && -+ (cmd->status == SAM_STAT_CHECK_CONDITION) && -+ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) && -+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len, -+ SCST_SENSE_ASCx_VALID, -+ 0, 0x2a, 0x01)) { -+ TRACE(TRACE_SCSI, "MODE PARAMETERS CHANGED UA (lun " -+ "%lld)", (long long unsigned int)cmd->lun); -+ cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS; -+ goto out; -+ } -+ } -+ -+ cmd->state = SCST_CMD_STATE_DEV_DONE; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_mode_select_checks(struct scst_cmd *cmd) -+{ -+ int res = SCST_CMD_STATE_RES_CONT_SAME; -+ -+ TRACE_ENTRY(); -+ -+ if (likely(scsi_status_is_good(cmd->status))) { -+ int atomic = scst_cmd_atomic(cmd); -+ if (unlikely((cmd->cdb[0] == MODE_SELECT) || -+ (cmd->cdb[0] == MODE_SELECT_10) || -+ (cmd->cdb[0] == LOG_SELECT))) { -+ struct scst_device *dev = cmd->dev; -+ int sl; -+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN]; -+ -+ if (atomic && (dev->scsi_dev != NULL)) { -+ TRACE_DBG("%s", "MODE/LOG SELECT: thread " -+ "context required"); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ TRACE(TRACE_SCSI, "MODE/LOG SELECT succeeded, " -+ "setting the SELECT UA (lun=%lld)", -+ (long long unsigned int)cmd->lun); -+ -+ spin_lock_bh(&dev->dev_lock); -+ if (cmd->cdb[0] == LOG_SELECT) { -+ sl = scst_set_sense(sense_buffer, -+ sizeof(sense_buffer), -+ dev->d_sense, -+ UNIT_ATTENTION, 0x2a, 0x02); -+ } else { -+ sl = scst_set_sense(sense_buffer, -+ sizeof(sense_buffer), -+ dev->d_sense, -+ UNIT_ATTENTION, 0x2a, 0x01); -+ } -+ scst_dev_check_set_local_UA(dev, cmd, sense_buffer, sl); -+ spin_unlock_bh(&dev->dev_lock); -+ -+ if (dev->scsi_dev != NULL) -+ scst_obtain_device_parameters(dev); -+ } -+ } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) && -+ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) && -+ /* mode parameters changed */ -+ (scst_analyze_sense(cmd->sense, cmd->sense_valid_len, -+ SCST_SENSE_ASCx_VALID, -+ 0, 0x2a, 0x01) || -+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len, -+ SCST_SENSE_ASC_VALID, -+ 0, 0x29, 0) /* reset */ || -+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len, -+ SCST_SENSE_ASC_VALID, -+ 0, 0x28, 0) /* medium changed */ || -+ /* cleared by another ini (just in case) */ -+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len, -+ SCST_SENSE_ASC_VALID, -+ 0, 0x2F, 0))) { -+ int atomic = scst_cmd_atomic(cmd); -+ if (atomic) { -+ TRACE_DBG("Possible parameters changed UA %x: " -+ "thread context required", cmd->sense[12]); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ TRACE(TRACE_SCSI, "Possible parameters changed UA %x " -+ "(LUN %lld): getting new parameters", cmd->sense[12], -+ (long long unsigned int)cmd->lun); -+ -+ scst_obtain_device_parameters(cmd->dev); -+ } else -+ BUG(); -+ -+ cmd->state = SCST_CMD_STATE_DEV_DONE; -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+static void scst_inc_check_expected_sn(struct scst_cmd *cmd) -+{ -+ if (likely(cmd->sn_set)) -+ scst_inc_expected_sn(cmd->cur_order_data, cmd->sn_slot); -+ -+ scst_make_deferred_commands_active(cmd->cur_order_data); -+} -+ -+static int scst_dev_done(struct scst_cmd *cmd) -+{ -+ int res = SCST_CMD_STATE_RES_CONT_SAME; -+ int state; -+ struct scst_device *dev = cmd->dev; -+ -+ TRACE_ENTRY(); -+ -+ state = SCST_CMD_STATE_PRE_XMIT_RESP; -+ -+ if (likely(!scst_is_cmd_fully_local(cmd)) && -+ likely(dev->handler->dev_done != NULL)) { -+ int rc; -+ -+ if (unlikely(!dev->handler->dev_done_atomic && -+ scst_cmd_atomic(cmd))) { -+ /* -+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_* -+ * optimization. -+ */ -+ TRACE_MGMT_DBG("Dev handler %s dev_done() needs thread " -+ "context, rescheduling", dev->handler->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ TRACE_DBG("Calling dev handler %s dev_done(%p)", -+ dev->handler->name, cmd); -+ scst_set_cur_start(cmd); -+ rc = dev->handler->dev_done(cmd); -+ scst_set_dev_done_time(cmd); -+ TRACE_DBG("Dev handler %s dev_done() returned %d", -+ dev->handler->name, rc); -+ if (rc != SCST_CMD_STATE_DEFAULT) -+ state = rc; -+ } -+ -+ switch (state) { -+#ifdef CONFIG_SCST_EXTRACHECKS -+ case SCST_CMD_STATE_PRE_XMIT_RESP: -+ case SCST_CMD_STATE_PARSE: -+ case SCST_CMD_STATE_PREPARE_SPACE: -+ case SCST_CMD_STATE_RDY_TO_XFER: -+ case SCST_CMD_STATE_TGT_PRE_EXEC: -+ case SCST_CMD_STATE_SEND_FOR_EXEC: -+ case SCST_CMD_STATE_START_EXEC: -+ case SCST_CMD_STATE_LOCAL_EXEC: -+ case SCST_CMD_STATE_REAL_EXEC: -+ case SCST_CMD_STATE_PRE_DEV_DONE: -+ case SCST_CMD_STATE_MODE_SELECT_CHECKS: -+ case SCST_CMD_STATE_DEV_DONE: -+ case SCST_CMD_STATE_XMIT_RESP: -+ case SCST_CMD_STATE_FINISHED: -+ case SCST_CMD_STATE_FINISHED_INTERNAL: -+#else -+ default: -+#endif -+ cmd->state = state; -+ break; -+ case SCST_CMD_STATE_NEED_THREAD_CTX: -+ TRACE_DBG("Dev handler %s dev_done() requested " -+ "thread context, rescheduling", -+ dev->handler->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+#ifdef CONFIG_SCST_EXTRACHECKS -+ default: -+ if (state >= 0) { -+ PRINT_ERROR("Dev handler %s dev_done() returned " -+ "invalid cmd state %d", -+ dev->handler->name, state); -+ } else { -+ PRINT_ERROR("Dev handler %s dev_done() returned " -+ "error %d", dev->handler->name, -+ state); -+ } -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ break; -+#endif -+ } -+ -+ scst_check_unblock_dev(cmd); -+ -+ if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec) -+ scst_inc_check_expected_sn(cmd); -+ -+ if (unlikely(cmd->internal)) -+ cmd->state = SCST_CMD_STATE_FINISHED_INTERNAL; -+ -+#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ -+ if (cmd->state != SCST_CMD_STATE_PRE_XMIT_RESP) { -+ /* We can't allow atomic command on the exec stages */ -+ if (scst_cmd_atomic(cmd)) { -+ switch (state) { -+ case SCST_CMD_STATE_TGT_PRE_EXEC: -+ case SCST_CMD_STATE_SEND_FOR_EXEC: -+ case SCST_CMD_STATE_START_EXEC: -+ case SCST_CMD_STATE_LOCAL_EXEC: -+ case SCST_CMD_STATE_REAL_EXEC: -+ TRACE_DBG("Atomic context and redirect, " -+ "rescheduling (cmd %p)", cmd); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ break; -+ } -+ } -+ } -+#endif -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+static int scst_pre_xmit_response(struct scst_cmd *cmd) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(cmd->internal); -+ -+#ifdef CONFIG_SCST_DEBUG_TM -+ if (cmd->tm_dbg_delayed && -+ !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { -+ if (scst_cmd_atomic(cmd)) { -+ TRACE_MGMT_DBG("%s", -+ "DEBUG_TM delayed cmd needs a thread"); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ return res; -+ } -+ TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second", -+ cmd, cmd->tag); -+ schedule_timeout_uninterruptible(HZ); -+ } -+#endif -+ -+ if (likely(cmd->tgt_dev != NULL)) { -+ /* -+ * Those counters protect from not getting too long processing -+ * latency, so we should decrement them after cmd completed. -+ */ -+ atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count); -+#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT -+ atomic_dec(&cmd->dev->dev_cmd_count); -+#endif -+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE)) -+ scst_on_hq_cmd_response(cmd); -+ -+ if (unlikely(!cmd->sent_for_exec)) { -+ TRACE_SN("cmd %p was not sent to mid-lev" -+ " (sn %d, set %d)", -+ cmd, cmd->sn, cmd->sn_set); -+ scst_unblock_deferred(cmd->cur_order_data, cmd); -+ cmd->sent_for_exec = 1; -+ } -+ } -+ -+ cmd->done = 1; -+ smp_mb(); /* to sync with scst_abort_cmd() */ -+ -+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) -+ scst_xmit_process_aborted_cmd(cmd); -+ else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION)) -+ scst_store_sense(cmd); -+ -+ if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) { -+ TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu), " -+ "skipping", cmd, (long long unsigned int)cmd->tag); -+ cmd->state = SCST_CMD_STATE_FINISHED; -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+ } -+ -+ if (unlikely(cmd->resid_possible)) -+ scst_adjust_resp_data_len(cmd); -+ else -+ cmd->adjusted_resp_data_len = cmd->resp_data_len; -+ -+ cmd->state = SCST_CMD_STATE_XMIT_RESP; -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+static int scst_xmit_response(struct scst_cmd *cmd) -+{ -+ struct scst_tgt_template *tgtt = cmd->tgtt; -+ int res, rc; -+ -+ TRACE_ENTRY(); -+ -+ EXTRACHECKS_BUG_ON(cmd->internal); -+ -+ if (unlikely(!tgtt->xmit_response_atomic && -+ scst_cmd_atomic(cmd))) { -+ /* -+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_* -+ * optimization. -+ */ -+ TRACE_MGMT_DBG("Target driver %s xmit_response() needs thread " -+ "context, rescheduling", tgtt->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ -+ while (1) { -+ int finished_cmds = atomic_read(&cmd->tgt->finished_cmds); -+ -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ cmd->state = SCST_CMD_STATE_XMIT_WAIT; -+ -+ TRACE_DBG("Calling xmit_response(%p)", cmd); -+ -+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) -+ if (trace_flag & TRACE_SND_BOT) { -+ int i, j; -+ struct scatterlist *sg; -+ if (cmd->tgt_sg != NULL) -+ sg = cmd->tgt_sg; -+ else -+ sg = cmd->sg; -+ if (sg != NULL) { -+ TRACE(TRACE_SND_BOT, "Xmitting data for cmd %p " -+ "(sg_cnt %d, sg %p, sg[0].page %p, buf %p, " -+ "resp len %d)", cmd, cmd->tgt_sg_cnt, -+ sg, (void *)sg_page(&sg[0]), sg_virt(sg), -+ cmd->resp_data_len); -+ for (i = 0, j = 0; i < cmd->tgt_sg_cnt; ++i, ++j) { -+ if (unlikely(sg_is_chain(&sg[j]))) { -+ sg = sg_chain_ptr(&sg[j]); -+ j = 0; -+ } -+ TRACE(TRACE_SND_BOT, "sg %d", j); -+ PRINT_BUFF_FLAG(TRACE_SND_BOT, -+ "Xmitting sg", sg_virt(&sg[j]), -+ sg[j].length); -+ } -+ } -+ } -+#endif -+ -+ if (tgtt->on_hw_pending_cmd_timeout != NULL) { -+ struct scst_session *sess = cmd->sess; -+ cmd->hw_pending_start = jiffies; -+ cmd->cmd_hw_pending = 1; -+ if (!test_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags)) { -+ TRACE_DBG("Sched HW pending work for sess %p " -+ "(max time %d)", sess, -+ tgtt->max_hw_pending_time); -+ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, -+ &sess->sess_aflags); -+ schedule_delayed_work(&sess->hw_pending_work, -+ tgtt->max_hw_pending_time * HZ); -+ } -+ } -+ -+ scst_set_cur_start(cmd); -+ -+#ifdef CONFIG_SCST_DEBUG_RETRY -+ if (((scst_random() % 100) == 77)) -+ rc = SCST_TGT_RES_QUEUE_FULL; -+ else -+#endif -+ rc = tgtt->xmit_response(cmd); -+ TRACE_DBG("xmit_response() returned %d", rc); -+ -+ if (likely(rc == SCST_TGT_RES_SUCCESS)) -+ goto out; -+ -+ scst_set_xmit_time(cmd); -+ -+ cmd->cmd_hw_pending = 0; -+ -+ /* Restore the previous state */ -+ cmd->state = SCST_CMD_STATE_XMIT_RESP; -+ -+ switch (rc) { -+ case SCST_TGT_RES_QUEUE_FULL: -+ if (scst_queue_retry_cmd(cmd, finished_cmds) == 0) -+ break; -+ else -+ continue; -+ -+ case SCST_TGT_RES_NEED_THREAD_CTX: -+ TRACE_DBG("Target driver %s xmit_response() " -+ "requested thread context, rescheduling", -+ tgtt->name); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ -+ default: -+ goto out_error; -+ } -+ break; -+ } -+ -+out: -+ /* Caution: cmd can be already dead here */ -+ TRACE_EXIT_HRES(res); -+ return res; -+ -+out_error: -+ if (rc == SCST_TGT_RES_FATAL_ERROR) { -+ PRINT_ERROR("Target driver %s xmit_response() returned " -+ "fatal error", tgtt->name); -+ } else { -+ PRINT_ERROR("Target driver %s xmit_response() returned " -+ "invalid value %d", tgtt->name, rc); -+ } -+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -+ cmd->state = SCST_CMD_STATE_FINISHED; -+ res = SCST_CMD_STATE_RES_CONT_SAME; -+ goto out; -+} -+ -+/** -+ * scst_tgt_cmd_done() - the command's processing done -+ * @cmd: SCST command -+ * @pref_context: preferred command execution context -+ * -+ * Description: -+ * Notifies SCST that the driver sent the response and the command -+ * can be freed now. Don't forget to set the delivery status, if it -+ * isn't success, using scst_set_delivery_status() before calling -+ * this function. The third argument sets preferred command execution -+ * context (see SCST_CONTEXT_* constants for details) -+ */ -+void scst_tgt_cmd_done(struct scst_cmd *cmd, -+ enum scst_exec_context pref_context) -+{ -+ TRACE_ENTRY(); -+ -+ BUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT); -+ -+ scst_set_xmit_time(cmd); -+ -+ cmd->cmd_hw_pending = 0; -+ -+ if (unlikely(cmd->tgt_dev == NULL)) -+ pref_context = SCST_CONTEXT_THREAD; -+ -+ cmd->state = SCST_CMD_STATE_FINISHED; -+ -+ scst_process_redirect_cmd(cmd, pref_context, 1); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL(scst_tgt_cmd_done); -+ -+static int scst_finish_cmd(struct scst_cmd *cmd) -+{ -+ int res; -+ struct scst_session *sess = cmd->sess; -+ struct scst_io_stat_entry *stat; -+ -+ TRACE_ENTRY(); -+ -+ scst_update_lat_stats(cmd); -+ -+ if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) { -+ if ((cmd->tgt_dev != NULL) && -+ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) { -+ /* This UA delivery failed, so we need to requeue it */ -+ if (scst_cmd_atomic(cmd) && -+ scst_is_ua_global(cmd->sense, cmd->sense_valid_len)) { -+ TRACE_MGMT_DBG("Requeuing of global UA for " -+ "failed cmd %p needs a thread", cmd); -+ res = SCST_CMD_STATE_RES_NEED_THREAD; -+ goto out; -+ } -+ scst_requeue_ua(cmd); -+ } -+ } -+ -+ atomic_dec(&sess->sess_cmd_count); -+ -+ spin_lock_irq(&sess->sess_list_lock); -+ -+ stat = &sess->io_stats[cmd->data_direction]; -+ stat->cmd_count++; -+ stat->io_byte_count += cmd->bufflen + cmd->out_bufflen; -+ -+ list_del(&cmd->sess_cmd_list_entry); -+ -+ /* -+ * Done under sess_list_lock to sync with scst_abort_cmd() without -+ * using extra barrier. -+ */ -+ cmd->finished = 1; -+ -+ spin_unlock_irq(&sess->sess_list_lock); -+ -+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { -+ TRACE_MGMT_DBG("Aborted cmd %p finished (cmd_ref %d)", -+ cmd, atomic_read(&cmd->cmd_ref)); -+ -+ scst_finish_cmd_mgmt(cmd); -+ } -+ -+ __scst_cmd_put(cmd); -+ -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/* -+ * No locks, but it must be externally serialized (see comment for -+ * scst_cmd_init_done() in scst.h) -+ */ -+static void scst_cmd_set_sn(struct scst_cmd *cmd) -+{ -+ struct scst_order_data *order_data = cmd->cur_order_data; -+ unsigned long flags; -+ -+ TRACE_ENTRY(); -+ -+ if (scst_is_implicit_hq_cmd(cmd) && -+ likely(cmd->queue_type == SCST_CMD_QUEUE_SIMPLE)) { -+ TRACE_SN("Implicit HQ cmd %p", cmd); -+ cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE; -+ } -+ -+ EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced); -+ -+ /* Optimized for lockless fast path */ -+ -+ scst_check_debug_sn(cmd); -+ -+#ifdef CONFIG_SCST_STRICT_SERIALIZING -+ cmd->queue_type = SCST_CMD_QUEUE_ORDERED; -+#endif -+ -+ if (cmd->dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) { -+ /* -+ * Not the best way, but good enough until there is a -+ * possibility to specify queue type during pass-through -+ * commands submission. -+ */ -+ cmd->queue_type = SCST_CMD_QUEUE_ORDERED; -+ } -+ -+ switch (cmd->queue_type) { -+ case SCST_CMD_QUEUE_SIMPLE: -+ case SCST_CMD_QUEUE_UNTAGGED: -+ if (likely(order_data->num_free_sn_slots >= 0)) { -+ /* -+ * atomic_inc_return() implies memory barrier to sync -+ * with scst_inc_expected_sn() -+ */ -+ if (atomic_inc_return(order_data->cur_sn_slot) == 1) { -+ order_data->curr_sn++; -+ TRACE_SN("Incremented curr_sn %d", -+ order_data->curr_sn); -+ } -+ cmd->sn_slot = order_data->cur_sn_slot; -+ cmd->sn = order_data->curr_sn; -+ -+ order_data->prev_cmd_ordered = 0; -+ } else { -+ TRACE(TRACE_MINOR, "***WARNING*** Not enough SN slots " -+ "%zd", ARRAY_SIZE(order_data->sn_slots)); -+ goto ordered; -+ } -+ break; -+ -+ case SCST_CMD_QUEUE_ORDERED: -+ TRACE_SN("ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]); -+ordered: -+ if (!order_data->prev_cmd_ordered) { -+ spin_lock_irqsave(&order_data->sn_lock, flags); -+ if (order_data->num_free_sn_slots >= 0) { -+ order_data->num_free_sn_slots--; -+ if (order_data->num_free_sn_slots >= 0) { -+ int i = 0; -+ /* Commands can finish in any order, so -+ * we don't know which slot is empty. -+ */ -+ while (1) { -+ order_data->cur_sn_slot++; -+ if (order_data->cur_sn_slot == -+ order_data->sn_slots + ARRAY_SIZE(order_data->sn_slots)) -+ order_data->cur_sn_slot = order_data->sn_slots; -+ -+ if (atomic_read(order_data->cur_sn_slot) == 0) -+ break; -+ -+ i++; -+ BUG_ON(i == ARRAY_SIZE(order_data->sn_slots)); -+ } -+ TRACE_SN("New cur SN slot %zd", -+ order_data->cur_sn_slot - -+ order_data->sn_slots); -+ } -+ } -+ spin_unlock_irqrestore(&order_data->sn_lock, flags); -+ } -+ order_data->prev_cmd_ordered = 1; -+ order_data->curr_sn++; -+ cmd->sn = order_data->curr_sn; -+ break; -+ -+ case SCST_CMD_QUEUE_HEAD_OF_QUEUE: -+ TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]); -+ spin_lock_irqsave(&order_data->sn_lock, flags); -+ order_data->hq_cmd_count++; -+ spin_unlock_irqrestore(&order_data->sn_lock, flags); -+ cmd->hq_cmd_inced = 1; -+ goto out; -+ -+ default: -+ BUG(); -+ } -+ -+ TRACE_SN("cmd(%p)->sn: %d (order_data %p, *cur_sn_slot %d, " -+ "num_free_sn_slots %d, prev_cmd_ordered %ld, " -+ "cur_sn_slot %zd)", cmd, cmd->sn, order_data, -+ atomic_read(order_data->cur_sn_slot), -+ order_data->num_free_sn_slots, order_data->prev_cmd_ordered, -+ order_data->cur_sn_slot - order_data->sn_slots); -+ -+ cmd->sn_set = 1; -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+ -+/* -+ * Returns 0 on success, > 0 when we need to wait for unblock, -+ * < 0 if there is no device (lun) or device type handler. -+ * -+ * No locks, but might be on IRQ, protection is done by the -+ * suspended activity. -+ */ -+static int scst_translate_lun(struct scst_cmd *cmd) -+{ -+ struct scst_tgt_dev *tgt_dev = NULL; -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ cmd->cpu_cmd_counter = scst_get(); -+ -+ if (likely(!test_bit(SCST_FLAG_SUSPENDED, &scst_flags))) { -+ struct list_head *head = -+ &cmd->sess->sess_tgt_dev_list[SESS_TGT_DEV_LIST_HASH_FN(cmd->lun)]; -+ TRACE_DBG("Finding tgt_dev for cmd %p (lun %lld)", cmd, -+ (long long unsigned int)cmd->lun); -+ res = -1; -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ if (tgt_dev->lun == cmd->lun) { -+ TRACE_DBG("tgt_dev %p found", tgt_dev); -+ -+ if (unlikely(tgt_dev->dev->handler == -+ &scst_null_devtype)) { -+ PRINT_INFO("Dev handler for device " -+ "%lld is NULL, the device will not " -+ "be visible remotely", -+ (long long unsigned int)cmd->lun); -+ break; -+ } -+ -+ cmd->cmd_threads = tgt_dev->active_cmd_threads; -+ cmd->tgt_dev = tgt_dev; -+ cmd->cur_order_data = tgt_dev->curr_order_data; -+ cmd->dev = tgt_dev->dev; -+ -+ res = 0; -+ break; -+ } -+ } -+ if (res != 0) { -+ TRACE(TRACE_MINOR, -+ "tgt_dev for LUN %lld not found, command to " -+ "unexisting LU (initiator %s, target %s)?", -+ (long long unsigned int)cmd->lun, -+ cmd->sess->initiator_name, cmd->tgt->tgt_name); -+ scst_put(cmd->cpu_cmd_counter); -+ } -+ } else { -+ TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping"); -+ scst_put(cmd->cpu_cmd_counter); -+ res = 1; -+ } -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* -+ * No locks, but might be on IRQ. -+ * -+ * Returns 0 on success, > 0 when we need to wait for unblock, -+ * < 0 if there is no device (lun) or device type handler. -+ */ -+static int __scst_init_cmd(struct scst_cmd *cmd) -+{ -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ res = scst_translate_lun(cmd); -+ if (likely(res == 0)) { -+ int cnt; -+ bool failure = false; -+ -+ cmd->state = SCST_CMD_STATE_PARSE; -+ -+ cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count); -+ if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) { -+ TRACE(TRACE_FLOW_CONTROL, -+ "Too many pending commands (%d) in " -+ "session, returning BUSY to initiator \"%s\"", -+ cnt, (cmd->sess->initiator_name[0] == '\0') ? -+ "Anonymous" : cmd->sess->initiator_name); -+ failure = true; -+ } -+ -+#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT -+ cnt = atomic_inc_return(&cmd->dev->dev_cmd_count); -+ if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) { -+ if (!failure) { -+ TRACE(TRACE_FLOW_CONTROL, -+ "Too many pending device " -+ "commands (%d), returning BUSY to " -+ "initiator \"%s\"", cnt, -+ (cmd->sess->initiator_name[0] == '\0') ? -+ "Anonymous" : -+ cmd->sess->initiator_name); -+ failure = true; -+ } -+ } -+#endif -+ -+ if (unlikely(failure)) -+ goto out_busy; -+ -+ /* -+ * SCST_IMPLICIT_HQ for unknown commands not implemented for -+ * case when set_sn_on_restart_cmd not set, because custom parse -+ * can reorder commands due to multithreaded processing. To -+ * implement it we need to implement all unknown commands as -+ * ORDERED in the beginning and post parse reprocess of -+ * queue_type to change it if needed. ToDo. -+ */ -+ scst_pre_parse(cmd); -+ -+ if (!cmd->set_sn_on_restart_cmd) -+ scst_cmd_set_sn(cmd); -+ } else if (res < 0) { -+ TRACE_DBG("Finishing cmd %p", cmd); -+ scst_set_cmd_error(cmd, -+ SCST_LOAD_SENSE(scst_sense_lun_not_supported)); -+ scst_set_cmd_abnormal_done_state(cmd); -+ } else -+ goto out; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_busy: -+ scst_set_busy(cmd); -+ scst_set_cmd_abnormal_done_state(cmd); -+ goto out; -+} -+ -+/* Called under scst_init_lock and IRQs disabled */ -+static void scst_do_job_init(void) -+ __releases(&scst_init_lock) -+ __acquires(&scst_init_lock) -+{ -+ struct scst_cmd *cmd; -+ int susp; -+ -+ TRACE_ENTRY(); -+ -+restart: -+ /* -+ * There is no need for read barrier here, because we don't care where -+ * this check will be done. -+ */ -+ susp = test_bit(SCST_FLAG_SUSPENDED, &scst_flags); -+ if (scst_init_poll_cnt > 0) -+ scst_init_poll_cnt--; -+ -+ list_for_each_entry(cmd, &scst_init_cmd_list, cmd_list_entry) { -+ int rc; -+ if (susp && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) -+ continue; -+ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { -+ spin_unlock_irq(&scst_init_lock); -+ rc = __scst_init_cmd(cmd); -+ spin_lock_irq(&scst_init_lock); -+ if (rc > 0) { -+ TRACE_MGMT_DBG("%s", -+ "FLAG SUSPENDED set, restarting"); -+ goto restart; -+ } -+ } else { -+ TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %llu)", -+ cmd, (long long unsigned int)cmd->tag); -+ scst_set_cmd_abnormal_done_state(cmd); -+ } -+ -+ /* -+ * Deleting cmd from init cmd list after __scst_init_cmd() -+ * is necessary to keep the check in scst_init_cmd() correct -+ * to preserve the commands order. -+ * -+ * We don't care about the race, when init cmd list is empty -+ * and one command detected that it just was not empty, so -+ * it's inserting to it, but another command at the same time -+ * seeing init cmd list empty and goes directly, because it -+ * could affect only commands from the same initiator to the -+ * same tgt_dev, but scst_cmd_init_done*() doesn't guarantee -+ * the order in case of simultaneous such calls anyway. -+ */ -+ TRACE_MGMT_DBG("Deleting cmd %p from init cmd list", cmd); -+ smp_wmb(); /* enforce the required order */ -+ list_del(&cmd->cmd_list_entry); -+ spin_unlock(&scst_init_lock); -+ -+ spin_lock(&cmd->cmd_threads->cmd_list_lock); -+ TRACE_MGMT_DBG("Adding cmd %p to active cmd list", cmd); -+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE)) -+ list_add(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ else -+ list_add_tail(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ wake_up(&cmd->cmd_threads->cmd_list_waitQ); -+ spin_unlock(&cmd->cmd_threads->cmd_list_lock); -+ -+ spin_lock(&scst_init_lock); -+ goto restart; -+ } -+ -+ /* It isn't really needed, but let's keep it */ -+ if (susp != test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) -+ goto restart; -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static inline int test_init_cmd_list(void) -+{ -+ int res = (!list_empty(&scst_init_cmd_list) && -+ !test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) || -+ unlikely(kthread_should_stop()) || -+ (scst_init_poll_cnt > 0); -+ return res; -+} -+ -+int scst_init_thread(void *arg) -+{ -+ TRACE_ENTRY(); -+ -+ PRINT_INFO("Init thread started, PID %d", current->pid); -+ -+ current->flags |= PF_NOFREEZE; -+ -+ set_user_nice(current, -10); -+ -+ spin_lock_irq(&scst_init_lock); -+ while (!kthread_should_stop()) { -+ wait_queue_t wait; -+ init_waitqueue_entry(&wait, current); -+ -+ if (!test_init_cmd_list()) { -+ add_wait_queue_exclusive(&scst_init_cmd_list_waitQ, -+ &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (test_init_cmd_list()) -+ break; -+ spin_unlock_irq(&scst_init_lock); -+ schedule(); -+ spin_lock_irq(&scst_init_lock); -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&scst_init_cmd_list_waitQ, &wait); -+ } -+ scst_do_job_init(); -+ } -+ spin_unlock_irq(&scst_init_lock); -+ -+ /* -+ * If kthread_should_stop() is true, we are guaranteed to be -+ * on the module unload, so scst_init_cmd_list must be empty. -+ */ -+ BUG_ON(!list_empty(&scst_init_cmd_list)); -+ -+ PRINT_INFO("Init thread PID %d finished", current->pid); -+ -+ TRACE_EXIT(); -+ return 0; -+} -+ -+/** -+ * scst_process_active_cmd() - process active command -+ * -+ * Description: -+ * Main SCST commands processing routing. Must be used only by dev handlers. -+ * -+ * Argument atomic is true, if function called in atomic context. -+ * -+ * Must be called with no locks held. -+ */ -+void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ /* -+ * Checkpatch will complain on the use of in_atomic() below. You -+ * can safely ignore this warning since in_atomic() is used here only -+ * for debugging purposes. -+ */ -+ EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled()); -+ EXTRACHECKS_WARN_ON((in_atomic() || in_interrupt()) && !atomic); -+ -+ cmd->atomic = atomic; -+ -+ TRACE_DBG("cmd %p, atomic %d", cmd, atomic); -+ -+ do { -+ switch (cmd->state) { -+ case SCST_CMD_STATE_PARSE: -+ res = scst_parse_cmd(cmd); -+ break; -+ -+ case SCST_CMD_STATE_PREPARE_SPACE: -+ res = scst_prepare_space(cmd); -+ break; -+ -+ case SCST_CMD_STATE_PREPROCESSING_DONE: -+ res = scst_preprocessing_done(cmd); -+ break; -+ -+ case SCST_CMD_STATE_RDY_TO_XFER: -+ res = scst_rdy_to_xfer(cmd); -+ break; -+ -+ case SCST_CMD_STATE_TGT_PRE_EXEC: -+ res = scst_tgt_pre_exec(cmd); -+ break; -+ -+ case SCST_CMD_STATE_SEND_FOR_EXEC: -+ if (tm_dbg_check_cmd(cmd) != 0) { -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ TRACE_MGMT_DBG("Skipping cmd %p (tag %llu), " -+ "because of TM DBG delay", cmd, -+ (long long unsigned int)cmd->tag); -+ break; -+ } -+ res = scst_send_for_exec(&cmd); -+ EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD); -+ /* -+ * !! At this point cmd, sess & tgt_dev can already be -+ * freed !! -+ */ -+ break; -+ -+ case SCST_CMD_STATE_START_EXEC: -+ res = scst_exec(&cmd); -+ EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD); -+ /* -+ * !! At this point cmd, sess & tgt_dev can already be -+ * freed !! -+ */ -+ break; -+ -+ case SCST_CMD_STATE_LOCAL_EXEC: -+ res = scst_local_exec(cmd); -+ EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD); -+ /* -+ * !! At this point cmd, sess & tgt_dev can already be -+ * freed !! -+ */ -+ break; -+ -+ case SCST_CMD_STATE_REAL_EXEC: -+ res = scst_real_exec(cmd); -+ EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD); -+ /* -+ * !! At this point cmd, sess & tgt_dev can already be -+ * freed !! -+ */ -+ break; -+ -+ case SCST_CMD_STATE_PRE_DEV_DONE: -+ res = scst_pre_dev_done(cmd); -+ EXTRACHECKS_BUG_ON((res == SCST_CMD_STATE_RES_NEED_THREAD) && -+ (cmd->state == SCST_CMD_STATE_PRE_DEV_DONE)); -+ break; -+ -+ case SCST_CMD_STATE_MODE_SELECT_CHECKS: -+ res = scst_mode_select_checks(cmd); -+ break; -+ -+ case SCST_CMD_STATE_DEV_DONE: -+ res = scst_dev_done(cmd); -+ break; -+ -+ case SCST_CMD_STATE_PRE_XMIT_RESP: -+ res = scst_pre_xmit_response(cmd); -+ EXTRACHECKS_BUG_ON(res == -+ SCST_CMD_STATE_RES_NEED_THREAD); -+ break; -+ -+ case SCST_CMD_STATE_XMIT_RESP: -+ res = scst_xmit_response(cmd); -+ break; -+ -+ case SCST_CMD_STATE_FINISHED: -+ res = scst_finish_cmd(cmd); -+ break; -+ -+ case SCST_CMD_STATE_FINISHED_INTERNAL: -+ res = scst_finish_internal_cmd(cmd); -+ EXTRACHECKS_BUG_ON(res == -+ SCST_CMD_STATE_RES_NEED_THREAD); -+ break; -+ -+ default: -+ PRINT_CRIT_ERROR("cmd (%p) in state %d, but shouldn't " -+ "be", cmd, cmd->state); -+ BUG(); -+ res = SCST_CMD_STATE_RES_CONT_NEXT; -+ break; -+ } -+ } while (res == SCST_CMD_STATE_RES_CONT_SAME); -+ -+ if (res == SCST_CMD_STATE_RES_CONT_NEXT) { -+ /* None */ -+ } else if (res == SCST_CMD_STATE_RES_NEED_THREAD) { -+ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock); -+#ifdef CONFIG_SCST_EXTRACHECKS -+ switch (cmd->state) { -+ case SCST_CMD_STATE_PARSE: -+ case SCST_CMD_STATE_PREPARE_SPACE: -+ case SCST_CMD_STATE_RDY_TO_XFER: -+ case SCST_CMD_STATE_TGT_PRE_EXEC: -+ case SCST_CMD_STATE_SEND_FOR_EXEC: -+ case SCST_CMD_STATE_START_EXEC: -+ case SCST_CMD_STATE_LOCAL_EXEC: -+ case SCST_CMD_STATE_REAL_EXEC: -+ case SCST_CMD_STATE_DEV_DONE: -+ case SCST_CMD_STATE_XMIT_RESP: -+#endif -+ TRACE_DBG("Adding cmd %p to head of active cmd list", -+ cmd); -+ list_add(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+#ifdef CONFIG_SCST_EXTRACHECKS -+ break; -+ default: -+ PRINT_CRIT_ERROR("cmd %p is in invalid state %d)", cmd, -+ cmd->state); -+ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock); -+ BUG(); -+ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock); -+ break; -+ } -+#endif -+ wake_up(&cmd->cmd_threads->cmd_list_waitQ); -+ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock); -+ } else -+ BUG(); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_process_active_cmd); -+ -+/* Called under cmd_list_lock and IRQs disabled */ -+static void scst_do_job_active(struct list_head *cmd_list, -+ spinlock_t *cmd_list_lock, bool atomic) -+ __releases(cmd_list_lock) -+ __acquires(cmd_list_lock) -+{ -+ TRACE_ENTRY(); -+ -+ while (!list_empty(cmd_list)) { -+ struct scst_cmd *cmd = list_entry(cmd_list->next, typeof(*cmd), -+ cmd_list_entry); -+ TRACE_DBG("Deleting cmd %p from active cmd list", cmd); -+ list_del(&cmd->cmd_list_entry); -+ spin_unlock_irq(cmd_list_lock); -+ scst_process_active_cmd(cmd, atomic); -+ spin_lock_irq(cmd_list_lock); -+ } -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static inline int test_cmd_threads(struct scst_cmd_threads *p_cmd_threads) -+{ -+ int res = !list_empty(&p_cmd_threads->active_cmd_list) || -+ unlikely(kthread_should_stop()) || -+ tm_dbg_is_release(); -+ return res; -+} -+ -+int scst_cmd_thread(void *arg) -+{ -+ struct scst_cmd_threads *p_cmd_threads = arg; -+ -+ TRACE_ENTRY(); -+ -+ PRINT_INFO("Processing thread %s (PID %d) started", current->comm, -+ current->pid); -+ -+#if 0 -+ set_user_nice(current, 10); -+#endif -+ current->flags |= PF_NOFREEZE; -+ -+ mutex_lock(&p_cmd_threads->io_context_mutex); -+ -+ WARN_ON(current->io_context); -+ -+ if (p_cmd_threads != &scst_main_cmd_threads) { -+ /* -+ * For linked IO contexts io_context might be not NULL while -+ * io_context 0. -+ */ -+ if (p_cmd_threads->io_context == NULL) { -+ p_cmd_threads->io_context = get_io_context(GFP_KERNEL, -1); -+ TRACE_MGMT_DBG("Alloced new IO context %p " -+ "(p_cmd_threads %p)", -+ p_cmd_threads->io_context, -+ p_cmd_threads); -+ /* -+ * Put the extra reference created by get_io_context() -+ * because we don't need it. -+ */ -+ put_io_context(p_cmd_threads->io_context); -+ } else { -+ current->io_context = ioc_task_link(p_cmd_threads->io_context); -+ TRACE_MGMT_DBG("Linked IO context %p " -+ "(p_cmd_threads %p)", p_cmd_threads->io_context, -+ p_cmd_threads); -+ } -+ p_cmd_threads->io_context_refcnt++; -+ } -+ -+ mutex_unlock(&p_cmd_threads->io_context_mutex); -+ -+ smp_wmb(); -+ p_cmd_threads->io_context_ready = true; -+ -+ spin_lock_irq(&p_cmd_threads->cmd_list_lock); -+ while (!kthread_should_stop()) { -+ wait_queue_t wait; -+ init_waitqueue_entry(&wait, current); -+ -+ if (!test_cmd_threads(p_cmd_threads)) { -+ add_wait_queue_exclusive_head( -+ &p_cmd_threads->cmd_list_waitQ, -+ &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (test_cmd_threads(p_cmd_threads)) -+ break; -+ spin_unlock_irq(&p_cmd_threads->cmd_list_lock); -+ schedule(); -+ spin_lock_irq(&p_cmd_threads->cmd_list_lock); -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&p_cmd_threads->cmd_list_waitQ, &wait); -+ } -+ -+ if (tm_dbg_is_release()) { -+ spin_unlock_irq(&p_cmd_threads->cmd_list_lock); -+ tm_dbg_check_released_cmds(); -+ spin_lock_irq(&p_cmd_threads->cmd_list_lock); -+ } -+ -+ scst_do_job_active(&p_cmd_threads->active_cmd_list, -+ &p_cmd_threads->cmd_list_lock, false); -+ } -+ spin_unlock_irq(&p_cmd_threads->cmd_list_lock); -+ -+ if (p_cmd_threads != &scst_main_cmd_threads) { -+ mutex_lock(&p_cmd_threads->io_context_mutex); -+ if (--p_cmd_threads->io_context_refcnt == 0) -+ p_cmd_threads->io_context = NULL; -+ mutex_unlock(&p_cmd_threads->io_context_mutex); -+ } -+ -+ PRINT_INFO("Processing thread %s (PID %d) finished", current->comm, -+ current->pid); -+ -+ TRACE_EXIT(); -+ return 0; -+} -+ -+void scst_cmd_tasklet(long p) -+{ -+ struct scst_percpu_info *i = (struct scst_percpu_info *)p; -+ -+ TRACE_ENTRY(); -+ -+ spin_lock_irq(&i->tasklet_lock); -+ scst_do_job_active(&i->tasklet_cmd_list, &i->tasklet_lock, true); -+ spin_unlock_irq(&i->tasklet_lock); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* -+ * Returns 0 on success, < 0 if there is no device handler or -+ * > 0 if SCST_FLAG_SUSPENDED set and SCST_FLAG_SUSPENDING - not. -+ * No locks, protection is done by the suspended activity. -+ */ -+static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd) -+{ -+ struct scst_tgt_dev *tgt_dev = NULL; -+ struct list_head *head; -+ int res = -1; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_DBG("Finding tgt_dev for mgmt cmd %p (lun %lld)", mcmd, -+ (long long unsigned int)mcmd->lun); -+ -+ mcmd->cpu_cmd_counter = scst_get(); -+ -+ if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags) && -+ !test_bit(SCST_FLAG_SUSPENDING, &scst_flags))) { -+ TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping"); -+ scst_put(mcmd->cpu_cmd_counter); -+ res = 1; -+ goto out; -+ } -+ -+ head = &mcmd->sess->sess_tgt_dev_list[SESS_TGT_DEV_LIST_HASH_FN(mcmd->lun)]; -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ if (tgt_dev->lun == mcmd->lun) { -+ TRACE_DBG("tgt_dev %p found", tgt_dev); -+ mcmd->mcmd_tgt_dev = tgt_dev; -+ res = 0; -+ break; -+ } -+ } -+ if (mcmd->mcmd_tgt_dev == NULL) -+ scst_put(mcmd->cpu_cmd_counter); -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/* No locks */ -+void scst_done_cmd_mgmt(struct scst_cmd *cmd) -+{ -+ struct scst_mgmt_cmd_stub *mstb, *t; -+ bool wake = 0; -+ unsigned long flags; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_MGMT_DBG("cmd %p done (tag %llu)", -+ cmd, (long long unsigned int)cmd->tag); -+ -+ spin_lock_irqsave(&scst_mcmd_lock, flags); -+ -+ list_for_each_entry_safe(mstb, t, &cmd->mgmt_cmd_list, -+ cmd_mgmt_cmd_list_entry) { -+ struct scst_mgmt_cmd *mcmd; -+ -+ if (!mstb->done_counted) -+ continue; -+ -+ mcmd = mstb->mcmd; -+ TRACE_MGMT_DBG("mcmd %p, mcmd->cmd_done_wait_count %d", -+ mcmd, mcmd->cmd_done_wait_count); -+ -+ mcmd->cmd_done_wait_count--; -+ -+ BUG_ON(mcmd->cmd_done_wait_count < 0); -+ -+ if (mcmd->cmd_done_wait_count > 0) { -+ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, " -+ "skipping", mcmd->cmd_done_wait_count); -+ goto check_free; -+ } -+ -+ if (mcmd->state == SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE) { -+ mcmd->state = SCST_MCMD_STATE_AFFECTED_CMDS_DONE; -+ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd " -+ "list", mcmd); -+ list_add_tail(&mcmd->mgmt_cmd_list_entry, -+ &scst_active_mgmt_cmd_list); -+ wake = 1; -+ } -+ -+check_free: -+ if (!mstb->finish_counted) { -+ TRACE_DBG("Releasing mstb %p", mstb); -+ list_del(&mstb->cmd_mgmt_cmd_list_entry); -+ mempool_free(mstb, scst_mgmt_stub_mempool); -+ } -+ } -+ -+ spin_unlock_irqrestore(&scst_mcmd_lock, flags); -+ -+ if (wake) -+ wake_up(&scst_mgmt_cmd_list_waitQ); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* Called under scst_mcmd_lock and IRQs disabled */ -+static void __scst_dec_finish_wait_count(struct scst_mgmt_cmd *mcmd, bool *wake) -+{ -+ TRACE_ENTRY(); -+ -+ mcmd->cmd_finish_wait_count--; -+ -+ BUG_ON(mcmd->cmd_finish_wait_count < 0); -+ -+ if (mcmd->cmd_finish_wait_count > 0) { -+ TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, " -+ "skipping", mcmd->cmd_finish_wait_count); -+ goto out; -+ } -+ -+ if (mcmd->cmd_done_wait_count > 0) { -+ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, " -+ "skipping", mcmd->cmd_done_wait_count); -+ goto out; -+ } -+ -+ if (mcmd->state == SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED) { -+ mcmd->state = SCST_MCMD_STATE_DONE; -+ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd " -+ "list", mcmd); -+ list_add_tail(&mcmd->mgmt_cmd_list_entry, -+ &scst_active_mgmt_cmd_list); -+ *wake = true; -+ } -+ -+out: -+ TRACE_EXIT(); -+ return; -+} -+ -+/** -+ * scst_prepare_async_mcmd() - prepare async management command -+ * -+ * Notifies SCST that management command is going to be async, i.e. -+ * will be completed in another context. -+ * -+ * No SCST locks supposed to be held on entrance. -+ */ -+void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd) -+{ -+ unsigned long flags; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_MGMT_DBG("Preparing mcmd %p for async execution " -+ "(cmd_finish_wait_count %d)", mcmd, -+ mcmd->cmd_finish_wait_count); -+ -+ spin_lock_irqsave(&scst_mcmd_lock, flags); -+ mcmd->cmd_finish_wait_count++; -+ spin_unlock_irqrestore(&scst_mcmd_lock, flags); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_prepare_async_mcmd); -+ -+/** -+ * scst_async_mcmd_completed() - async management command completed -+ * -+ * Notifies SCST that async management command, prepared by -+ * scst_prepare_async_mcmd(), completed. -+ * -+ * No SCST locks supposed to be held on entrance. -+ */ -+void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status) -+{ -+ unsigned long flags; -+ bool wake = false; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_MGMT_DBG("Async mcmd %p completed (status %d)", mcmd, status); -+ -+ spin_lock_irqsave(&scst_mcmd_lock, flags); -+ -+ if (status != SCST_MGMT_STATUS_SUCCESS) -+ mcmd->status = status; -+ -+ __scst_dec_finish_wait_count(mcmd, &wake); -+ -+ spin_unlock_irqrestore(&scst_mcmd_lock, flags); -+ -+ if (wake) -+ wake_up(&scst_mgmt_cmd_list_waitQ); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_async_mcmd_completed); -+ -+/* No locks */ -+static void scst_finish_cmd_mgmt(struct scst_cmd *cmd) -+{ -+ struct scst_mgmt_cmd_stub *mstb, *t; -+ bool wake = false; -+ unsigned long flags; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_MGMT_DBG("cmd %p finished (tag %llu)", -+ cmd, (long long unsigned int)cmd->tag); -+ -+ spin_lock_irqsave(&scst_mcmd_lock, flags); -+ -+ list_for_each_entry_safe(mstb, t, &cmd->mgmt_cmd_list, -+ cmd_mgmt_cmd_list_entry) { -+ struct scst_mgmt_cmd *mcmd = mstb->mcmd; -+ -+ TRACE_MGMT_DBG("mcmd %p, mcmd->cmd_finish_wait_count %d", mcmd, -+ mcmd->cmd_finish_wait_count); -+ -+ BUG_ON(!mstb->finish_counted); -+ -+ if (cmd->completed) -+ mcmd->completed_cmd_count++; -+ -+ __scst_dec_finish_wait_count(mcmd, &wake); -+ -+ TRACE_DBG("Releasing mstb %p", mstb); -+ list_del(&mstb->cmd_mgmt_cmd_list_entry); -+ mempool_free(mstb, scst_mgmt_stub_mempool); -+ } -+ -+ spin_unlock_irqrestore(&scst_mcmd_lock, flags); -+ -+ if (wake) -+ wake_up(&scst_mgmt_cmd_list_waitQ); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static int scst_call_dev_task_mgmt_fn(struct scst_mgmt_cmd *mcmd, -+ struct scst_tgt_dev *tgt_dev, int set_status) -+{ -+ int res = SCST_DEV_TM_NOT_COMPLETED; -+ struct scst_dev_type *h = tgt_dev->dev->handler; -+ -+ if (h->task_mgmt_fn) { -+ TRACE_MGMT_DBG("Calling dev handler %s task_mgmt_fn(fn=%d)", -+ h->name, mcmd->fn); -+ res = h->task_mgmt_fn(mcmd, tgt_dev); -+ TRACE_MGMT_DBG("Dev handler %s task_mgmt_fn() returned %d", -+ h->name, res); -+ if (set_status && (res != SCST_DEV_TM_NOT_COMPLETED)) -+ mcmd->status = res; -+ } -+ return res; -+} -+ -+static inline int scst_is_strict_mgmt_fn(int mgmt_fn) -+{ -+ switch (mgmt_fn) { -+#ifdef CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING -+ case SCST_ABORT_TASK: -+#endif -+#if 0 -+ case SCST_ABORT_TASK_SET: -+ case SCST_CLEAR_TASK_SET: -+#endif -+ return 1; -+ default: -+ return 0; -+ } -+} -+ -+/* -+ * Must be called under sess_list_lock to sync with finished flag assignment in -+ * scst_finish_cmd() -+ */ -+void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, -+ bool other_ini, bool call_dev_task_mgmt_fn) -+{ -+ unsigned long flags; -+ static DEFINE_SPINLOCK(other_ini_lock); -+ -+ TRACE_ENTRY(); -+ -+ TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "Aborting cmd %p (tag %llu, op %x)", -+ cmd, (long long unsigned int)cmd->tag, cmd->cdb[0]); -+ -+ /* To protect from concurrent aborts */ -+ spin_lock_irqsave(&other_ini_lock, flags); -+ -+ if (other_ini) { -+ struct scst_device *dev = NULL; -+ -+ /* Might be necessary if command aborted several times */ -+ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) -+ set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); -+ -+ /* Necessary for scst_xmit_process_aborted_cmd */ -+ if (cmd->dev != NULL) -+ dev = cmd->dev; -+ else if ((mcmd != NULL) && (mcmd->mcmd_tgt_dev != NULL)) -+ dev = mcmd->mcmd_tgt_dev->dev; -+ -+ if (dev != NULL) { -+ if (dev->tas) -+ set_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags); -+ } else -+ PRINT_WARNING("Abort cmd %p from other initiator, but " -+ "neither cmd, nor mcmd %p have tgt_dev set, so " -+ "TAS information can be lost", cmd, mcmd); -+ } else { -+ /* Might be necessary if command aborted several times */ -+ clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); -+ } -+ -+ set_bit(SCST_CMD_ABORTED, &cmd->cmd_flags); -+ -+ spin_unlock_irqrestore(&other_ini_lock, flags); -+ -+ /* -+ * To sync with setting cmd->done in scst_pre_xmit_response() (with -+ * scst_finish_cmd() we synced by using sess_list_lock) and with -+ * setting UA for aborted cmd in scst_set_pending_UA(). -+ */ -+ smp_mb__after_set_bit(); -+ -+ if (cmd->tgt_dev == NULL) { -+ spin_lock_irqsave(&scst_init_lock, flags); -+ scst_init_poll_cnt++; -+ spin_unlock_irqrestore(&scst_init_lock, flags); -+ wake_up(&scst_init_cmd_list_waitQ); -+ } -+ -+ if (!cmd->finished && call_dev_task_mgmt_fn && (cmd->tgt_dev != NULL)) -+ scst_call_dev_task_mgmt_fn(mcmd, cmd->tgt_dev, 1); -+ -+ spin_lock_irqsave(&scst_mcmd_lock, flags); -+ if ((mcmd != NULL) && !cmd->finished) { -+ struct scst_mgmt_cmd_stub *mstb; -+ -+ mstb = mempool_alloc(scst_mgmt_stub_mempool, GFP_ATOMIC); -+ if (mstb == NULL) { -+ PRINT_CRIT_ERROR("Allocation of management command " -+ "stub failed (mcmd %p, cmd %p)", mcmd, cmd); -+ goto unlock; -+ } -+ memset(mstb, 0, sizeof(*mstb)); -+ -+ TRACE_DBG("mstb %p, mcmd %p", mstb, mcmd); -+ -+ mstb->mcmd = mcmd; -+ -+ /* -+ * Delay the response until the command's finish in order to -+ * guarantee that "no further responses from the task are sent -+ * to the SCSI initiator port" after response from the TM -+ * function is sent (SAM). Plus, we must wait here to be sure -+ * that we won't receive double commands with the same tag. -+ * Moreover, if we don't wait here, we might have a possibility -+ * for data corruption, when aborted and reported as completed -+ * command actually gets executed *after* new commands sent -+ * after this TM command completed. -+ */ -+ -+ if (cmd->sent_for_exec && !cmd->done) { -+ TRACE_MGMT_DBG("cmd %p (tag %llu) is being executed", -+ cmd, (long long unsigned int)cmd->tag); -+ mstb->done_counted = 1; -+ mcmd->cmd_done_wait_count++; -+ } -+ -+ /* -+ * We don't have to wait the command's status delivery finish -+ * to other initiators + it can affect MPIO failover. -+ */ -+ if (!other_ini) { -+ mstb->finish_counted = 1; -+ mcmd->cmd_finish_wait_count++; -+ } -+ -+ if (mstb->done_counted || mstb->finish_counted) { -+ TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "cmd %p (tag %llu, " -+ "sn %u) being executed/xmitted (state %d, " -+ "op %x, proc time %ld sec., timeout %d sec.), " -+ "deferring ABORT (cmd_done_wait_count %d, " -+ "cmd_finish_wait_count %d)", cmd, -+ (long long unsigned int)cmd->tag, -+ cmd->sn, cmd->state, cmd->cdb[0], -+ (long)(jiffies - cmd->start_time) / HZ, -+ cmd->timeout / HZ, mcmd->cmd_done_wait_count, -+ mcmd->cmd_finish_wait_count); -+ /* -+ * cmd can't die here or sess_list_lock already taken -+ * and cmd is in the sess list -+ */ -+ list_add_tail(&mstb->cmd_mgmt_cmd_list_entry, -+ &cmd->mgmt_cmd_list); -+ } else { -+ /* We don't need to wait for this cmd */ -+ mempool_free(mstb, scst_mgmt_stub_mempool); -+ } -+ -+ if (cmd->tgtt->on_abort_cmd) -+ cmd->tgtt->on_abort_cmd(cmd); -+ } -+ -+unlock: -+ spin_unlock_irqrestore(&scst_mcmd_lock, flags); -+ -+ tm_dbg_release_cmd(cmd); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* No locks. Returns 0, if mcmd should be processed further. */ -+static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd) -+{ -+ int res; -+ -+ spin_lock_irq(&scst_mcmd_lock); -+ -+ switch (mcmd->state) { -+ case SCST_MCMD_STATE_INIT: -+ case SCST_MCMD_STATE_EXEC: -+ if (mcmd->cmd_done_wait_count == 0) { -+ mcmd->state = SCST_MCMD_STATE_AFFECTED_CMDS_DONE; -+ res = 0; -+ } else { -+ TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, -+ "cmd_done_wait_count(%d) not 0, " -+ "preparing to wait", mcmd->cmd_done_wait_count); -+ mcmd->state = SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE; -+ res = -1; -+ } -+ break; -+ -+ case SCST_MCMD_STATE_AFFECTED_CMDS_DONE: -+ if (mcmd->cmd_finish_wait_count == 0) { -+ mcmd->state = SCST_MCMD_STATE_DONE; -+ res = 0; -+ } else { -+ TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, -+ "cmd_finish_wait_count(%d) not 0, " -+ "preparing to wait", -+ mcmd->cmd_finish_wait_count); -+ mcmd->state = SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED; -+ res = -1; -+ } -+ break; -+ -+ case SCST_MCMD_STATE_DONE: -+ mcmd->state = SCST_MCMD_STATE_FINISHED; -+ res = 0; -+ break; -+ -+ default: -+ PRINT_CRIT_ERROR("Wrong mcmd %p state %d (fn %d, " -+ "cmd_finish_wait_count %d, cmd_done_wait_count %d)", -+ mcmd, mcmd->state, mcmd->fn, -+ mcmd->cmd_finish_wait_count, mcmd->cmd_done_wait_count); -+ spin_unlock_irq(&scst_mcmd_lock); -+ res = -1; -+ BUG(); -+ goto out; -+ } -+ -+ spin_unlock_irq(&scst_mcmd_lock); -+ -+out: -+ return res; -+} -+ -+/* IRQs supposed to be disabled */ -+static bool __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd, -+ struct list_head *list_entry) -+{ -+ bool res; -+ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { -+ list_del(list_entry); -+ spin_lock(&cmd->cmd_threads->cmd_list_lock); -+ list_add_tail(&cmd->cmd_list_entry, -+ &cmd->cmd_threads->active_cmd_list); -+ wake_up(&cmd->cmd_threads->cmd_list_waitQ); -+ spin_unlock(&cmd->cmd_threads->cmd_list_lock); -+ res = 1; -+ } else -+ res = 0; -+ return res; -+} -+ -+static void scst_unblock_aborted_cmds(int scst_mutex_held) -+{ -+ struct scst_device *dev; -+ -+ TRACE_ENTRY(); -+ -+ if (!scst_mutex_held) -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { -+ struct scst_cmd *cmd, *tcmd; -+ struct scst_tgt_dev *tgt_dev; -+ spin_lock_bh(&dev->dev_lock); -+ local_irq_disable(); -+ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list, -+ blocked_cmd_list_entry) { -+ if (__scst_check_unblock_aborted_cmd(cmd, -+ &cmd->blocked_cmd_list_entry)) { -+ TRACE_MGMT_DBG("Unblock aborted blocked cmd %p", -+ cmd); -+ } -+ } -+ local_irq_enable(); -+ spin_unlock_bh(&dev->dev_lock); -+ -+ local_irq_disable(); -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ struct scst_order_data *order_data = tgt_dev->curr_order_data; -+ spin_lock(&order_data->sn_lock); -+ list_for_each_entry_safe(cmd, tcmd, -+ &order_data->deferred_cmd_list, -+ sn_cmd_list_entry) { -+ if (__scst_check_unblock_aborted_cmd(cmd, -+ &cmd->sn_cmd_list_entry)) { -+ TRACE_MGMT_DBG("Unblocked aborted SN " -+ "cmd %p (sn %u)", -+ cmd, cmd->sn); -+ order_data->def_cmd_count--; -+ } -+ } -+ spin_unlock(&order_data->sn_lock); -+ } -+ local_irq_enable(); -+ } -+ -+ if (!scst_mutex_held) -+ mutex_unlock(&scst_mutex); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static void __scst_abort_task_set(struct scst_mgmt_cmd *mcmd, -+ struct scst_tgt_dev *tgt_dev) -+{ -+ struct scst_cmd *cmd; -+ struct scst_session *sess = tgt_dev->sess; -+ bool other_ini; -+ -+ TRACE_ENTRY(); -+ -+ if ((mcmd->fn == SCST_PR_ABORT_ALL) && -+ (mcmd->origin_pr_cmd->sess != sess)) -+ other_ini = true; -+ else -+ other_ini = false; -+ -+ spin_lock_irq(&sess->sess_list_lock); -+ -+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess); -+ list_for_each_entry(cmd, &sess->sess_cmd_list, -+ sess_cmd_list_entry) { -+ if ((mcmd->fn == SCST_PR_ABORT_ALL) && -+ (mcmd->origin_pr_cmd == cmd)) -+ continue; -+ if ((cmd->tgt_dev == tgt_dev) || -+ ((cmd->tgt_dev == NULL) && -+ (cmd->lun == tgt_dev->lun))) { -+ if (mcmd->cmd_sn_set) { -+ BUG_ON(!cmd->tgt_sn_set); -+ if (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) || -+ (mcmd->cmd_sn == cmd->tgt_sn)) -+ continue; -+ } -+ scst_abort_cmd(cmd, mcmd, other_ini, 0); -+ } -+ } -+ spin_unlock_irq(&sess->sess_list_lock); -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* Returns 0 if the command processing should be continued, <0 otherwise */ -+static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd) -+{ -+ int res; -+ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev; -+ -+ TRACE(TRACE_MGMT, "Aborting task set (lun=%lld, mcmd=%p)", -+ (long long unsigned int)tgt_dev->lun, mcmd); -+ -+ __scst_abort_task_set(mcmd, tgt_dev); -+ -+ if (mcmd->fn == SCST_PR_ABORT_ALL) { -+ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_cnt = -+ mcmd->origin_pr_cmd->pr_abort_counter; -+ if (atomic_dec_and_test(&pr_cnt->pr_aborting_cnt)) -+ complete_all(&pr_cnt->pr_aborting_cmpl); -+ } -+ -+ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "ABORT TASK SET/PR ABORT", 0); -+ -+ scst_unblock_aborted_cmds(0); -+ -+ scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_is_cmd_belongs_to_dev(struct scst_cmd *cmd, -+ struct scst_device *dev) -+{ -+ struct scst_tgt_dev *tgt_dev = NULL; -+ struct list_head *head; -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_DBG("Finding match for dev %s and cmd %p (lun %lld)", dev->virt_name, -+ cmd, (long long unsigned int)cmd->lun); -+ -+ head = &cmd->sess->sess_tgt_dev_list[SESS_TGT_DEV_LIST_HASH_FN(cmd->lun)]; -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ if (tgt_dev->lun == cmd->lun) { -+ TRACE_DBG("dev %s found", tgt_dev->dev->virt_name); -+ res = (tgt_dev->dev == dev); -+ goto out; -+ } -+ } -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/* Returns 0 if the command processing should be continued, <0 otherwise */ -+static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd) -+{ -+ int res; -+ struct scst_device *dev = mcmd->mcmd_tgt_dev->dev; -+ struct scst_tgt_dev *tgt_dev; -+ LIST_HEAD(UA_tgt_devs); -+ -+ TRACE_ENTRY(); -+ -+ TRACE(TRACE_MGMT, "Clearing task set (lun=%lld, mcmd=%p)", -+ (long long unsigned int)mcmd->lun, mcmd); -+ -+#if 0 /* we are SAM-3 */ -+ /* -+ * When a logical unit is aborting one or more tasks from a SCSI -+ * initiator port with the TASK ABORTED status it should complete all -+ * of those tasks before entering additional tasks from that SCSI -+ * initiator port into the task set - SAM2 -+ */ -+ mcmd->needs_unblocking = 1; -+ spin_lock_bh(&dev->dev_lock); -+ scst_block_dev(dev); -+ spin_unlock_bh(&dev->dev_lock); -+#endif -+ -+ __scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev); -+ -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ struct scst_session *sess = tgt_dev->sess; -+ struct scst_cmd *cmd; -+ int aborted = 0; -+ -+ if (tgt_dev == mcmd->mcmd_tgt_dev) -+ continue; -+ -+ spin_lock_irq(&sess->sess_list_lock); -+ -+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess); -+ list_for_each_entry(cmd, &sess->sess_cmd_list, -+ sess_cmd_list_entry) { -+ if ((cmd->dev == dev) || -+ ((cmd->dev == NULL) && -+ scst_is_cmd_belongs_to_dev(cmd, dev))) { -+ scst_abort_cmd(cmd, mcmd, 1, 0); -+ aborted = 1; -+ } -+ } -+ spin_unlock_irq(&sess->sess_list_lock); -+ -+ if (aborted) -+ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry, -+ &UA_tgt_devs); -+ } -+ -+ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "CLEAR TASK SET", 0); -+ -+ scst_unblock_aborted_cmds(1); -+ -+ mutex_unlock(&scst_mutex); -+ -+ if (!dev->tas) { -+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN]; -+ int sl; -+ -+ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer), -+ dev->d_sense, -+ SCST_LOAD_SENSE(scst_sense_cleared_by_another_ini_UA)); -+ -+ list_for_each_entry(tgt_dev, &UA_tgt_devs, -+ extra_tgt_dev_list_entry) { -+ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0); -+ } -+ } -+ -+ scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 0); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* Returns 0 if the command processing should be continued, -+ * >0, if it should be requeued, <0 otherwise */ -+static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd) -+{ -+ int res = 0, rc; -+ -+ TRACE_ENTRY(); -+ -+ switch (mcmd->fn) { -+ case SCST_ABORT_TASK: -+ { -+ struct scst_session *sess = mcmd->sess; -+ struct scst_cmd *cmd; -+ -+ spin_lock_irq(&sess->sess_list_lock); -+ cmd = __scst_find_cmd_by_tag(sess, mcmd->tag, true); -+ if (cmd == NULL) { -+ TRACE_MGMT_DBG("ABORT TASK: command " -+ "for tag %llu not found", -+ (long long unsigned int)mcmd->tag); -+ mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST; -+ spin_unlock_irq(&sess->sess_list_lock); -+ res = scst_set_mcmd_next_state(mcmd); -+ goto out; -+ } -+ __scst_cmd_get(cmd); -+ spin_unlock_irq(&sess->sess_list_lock); -+ TRACE_DBG("Cmd to abort %p for tag %llu found", -+ cmd, (long long unsigned int)mcmd->tag); -+ mcmd->cmd_to_abort = cmd; -+ mcmd->state = SCST_MCMD_STATE_EXEC; -+ break; -+ } -+ -+ case SCST_TARGET_RESET: -+ case SCST_NEXUS_LOSS_SESS: -+ case SCST_ABORT_ALL_TASKS_SESS: -+ case SCST_NEXUS_LOSS: -+ case SCST_ABORT_ALL_TASKS: -+ case SCST_UNREG_SESS_TM: -+ mcmd->state = SCST_MCMD_STATE_EXEC; -+ break; -+ -+ case SCST_ABORT_TASK_SET: -+ case SCST_CLEAR_ACA: -+ case SCST_CLEAR_TASK_SET: -+ case SCST_LUN_RESET: -+ case SCST_PR_ABORT_ALL: -+ rc = scst_mgmt_translate_lun(mcmd); -+ if (rc == 0) -+ mcmd->state = SCST_MCMD_STATE_EXEC; -+ else if (rc < 0) { -+ PRINT_ERROR("Corresponding device for LUN %lld not " -+ "found", (long long unsigned int)mcmd->lun); -+ mcmd->status = SCST_MGMT_STATUS_LUN_NOT_EXIST; -+ res = scst_set_mcmd_next_state(mcmd); -+ } else -+ res = rc; -+ break; -+ -+ default: -+ BUG(); -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* Returns 0 if the command processing should be continued, <0 otherwise */ -+static int scst_target_reset(struct scst_mgmt_cmd *mcmd) -+{ -+ int res, rc; -+ struct scst_device *dev; -+ struct scst_acg *acg = mcmd->sess->acg; -+ struct scst_acg_dev *acg_dev; -+ int cont, c; -+ LIST_HEAD(host_devs); -+ -+ TRACE_ENTRY(); -+ -+ TRACE(TRACE_MGMT, "Target reset (mcmd %p, cmd count %d)", -+ mcmd, atomic_read(&mcmd->sess->sess_cmd_count)); -+ -+ mcmd->needs_unblocking = 1; -+ -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) { -+ struct scst_device *d; -+ struct scst_tgt_dev *tgt_dev; -+ int found = 0; -+ -+ dev = acg_dev->dev; -+ -+ spin_lock_bh(&dev->dev_lock); -+ scst_block_dev(dev); -+ scst_process_reset(dev, mcmd->sess, NULL, mcmd, true); -+ spin_unlock_bh(&dev->dev_lock); -+ -+ cont = 0; -+ c = 0; -+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, -+ dev_tgt_dev_list_entry) { -+ cont = 1; -+ if (mcmd->sess == tgt_dev->sess) { -+ rc = scst_call_dev_task_mgmt_fn(mcmd, -+ tgt_dev, 0); -+ if (rc == SCST_DEV_TM_NOT_COMPLETED) -+ c = 1; -+ else if ((rc < 0) && -+ (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) -+ mcmd->status = rc; -+ break; -+ } -+ } -+ if (cont && !c) -+ continue; -+ -+ if (dev->scsi_dev == NULL) -+ continue; -+ -+ list_for_each_entry(d, &host_devs, tm_dev_list_entry) { -+ if (dev->scsi_dev->host->host_no == -+ d->scsi_dev->host->host_no) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) -+ list_add_tail(&dev->tm_dev_list_entry, &host_devs); -+ -+ tm_dbg_task_mgmt(dev, "TARGET RESET", 0); -+ } -+ -+ scst_unblock_aborted_cmds(1); -+ -+ /* -+ * We suppose here that for all commands that already on devices -+ * on/after scsi_reset_provider() completion callbacks will be called. -+ */ -+ -+ list_for_each_entry(dev, &host_devs, tm_dev_list_entry) { -+ /* dev->scsi_dev must be non-NULL here */ -+ TRACE(TRACE_MGMT, "Resetting host %d bus ", -+ dev->scsi_dev->host->host_no); -+ rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_TARGET); -+ TRACE(TRACE_MGMT, "Result of host %d target reset: %s", -+ dev->scsi_dev->host->host_no, -+ (rc == SUCCESS) ? "SUCCESS" : "FAILED"); -+#if 0 -+ if ((rc != SUCCESS) && -+ (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) { -+ /* -+ * SCSI_TRY_RESET_BUS is also done by -+ * scsi_reset_provider() -+ */ -+ mcmd->status = SCST_MGMT_STATUS_FAILED; -+ } -+#else -+ /* -+ * scsi_reset_provider() returns very weird status, so let's -+ * always succeed -+ */ -+#endif -+ } -+ -+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) { -+ dev = acg_dev->dev; -+ if (dev->scsi_dev != NULL) -+ dev->scsi_dev->was_reset = 0; -+ } -+ -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* Returns 0 if the command processing should be continued, <0 otherwise */ -+static int scst_lun_reset(struct scst_mgmt_cmd *mcmd) -+{ -+ int res, rc; -+ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev; -+ struct scst_device *dev = tgt_dev->dev; -+ -+ TRACE_ENTRY(); -+ -+ TRACE(TRACE_MGMT, "Resetting LUN %lld (mcmd %p)", -+ (long long unsigned int)tgt_dev->lun, mcmd); -+ -+ mcmd->needs_unblocking = 1; -+ -+ spin_lock_bh(&dev->dev_lock); -+ scst_block_dev(dev); -+ scst_process_reset(dev, mcmd->sess, NULL, mcmd, true); -+ spin_unlock_bh(&dev->dev_lock); -+ -+ rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 1); -+ if (rc != SCST_DEV_TM_NOT_COMPLETED) -+ goto out_tm_dbg; -+ -+ if (dev->scsi_dev != NULL) { -+ TRACE(TRACE_MGMT, "Resetting host %d bus ", -+ dev->scsi_dev->host->host_no); -+ rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_DEVICE); -+#if 0 -+ if (rc != SUCCESS && mcmd->status == SCST_MGMT_STATUS_SUCCESS) -+ mcmd->status = SCST_MGMT_STATUS_FAILED; -+#else -+ /* -+ * scsi_reset_provider() returns very weird status, so let's -+ * always succeed -+ */ -+#endif -+ dev->scsi_dev->was_reset = 0; -+ } -+ -+ scst_unblock_aborted_cmds(0); -+ -+out_tm_dbg: -+ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "LUN RESET", 0); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* scst_mutex supposed to be held */ -+static void scst_do_nexus_loss_sess(struct scst_mgmt_cmd *mcmd) -+{ -+ int i; -+ struct scst_session *sess = mcmd->sess; -+ struct scst_tgt_dev *tgt_dev; -+ -+ TRACE_ENTRY(); -+ -+ for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { -+ struct list_head *head = &sess->sess_tgt_dev_list[i]; -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ scst_nexus_loss(tgt_dev, -+ (mcmd->fn != SCST_UNREG_SESS_TM)); -+ } -+ } -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* Returns 0 if the command processing should be continued, <0 otherwise */ -+static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd, -+ int nexus_loss) -+{ -+ int res; -+ int i; -+ struct scst_session *sess = mcmd->sess; -+ struct scst_tgt_dev *tgt_dev; -+ -+ TRACE_ENTRY(); -+ -+ if (nexus_loss) { -+ TRACE_MGMT_DBG("Nexus loss for sess %p (mcmd %p)", -+ sess, mcmd); -+ } else { -+ TRACE_MGMT_DBG("Aborting all from sess %p (mcmd %p)", -+ sess, mcmd); -+ } -+ -+ mutex_lock(&scst_mutex); -+ -+ for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { -+ struct list_head *head = &sess->sess_tgt_dev_list[i]; -+ list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { -+ int rc; -+ -+ __scst_abort_task_set(mcmd, tgt_dev); -+ -+ rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0); -+ if (rc < 0 && mcmd->status == SCST_MGMT_STATUS_SUCCESS) -+ mcmd->status = rc; -+ -+ tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS SESS or " -+ "ABORT ALL SESS or UNREG SESS", -+ (mcmd->fn == SCST_UNREG_SESS_TM)); -+ } -+ } -+ -+ scst_unblock_aborted_cmds(1); -+ -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* scst_mutex supposed to be held */ -+static void scst_do_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd) -+{ -+ int i; -+ struct scst_tgt *tgt = mcmd->sess->tgt; -+ struct scst_session *sess; -+ -+ TRACE_ENTRY(); -+ -+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { -+ for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { -+ struct list_head *head = &sess->sess_tgt_dev_list[i]; -+ struct scst_tgt_dev *tgt_dev; -+ list_for_each_entry(tgt_dev, head, -+ sess_tgt_dev_list_entry) { -+ scst_nexus_loss(tgt_dev, true); -+ } -+ } -+ } -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd, -+ int nexus_loss) -+{ -+ int res; -+ int i; -+ struct scst_tgt *tgt = mcmd->sess->tgt; -+ struct scst_session *sess; -+ -+ TRACE_ENTRY(); -+ -+ if (nexus_loss) { -+ TRACE_MGMT_DBG("I_T Nexus loss (tgt %p, mcmd %p)", -+ tgt, mcmd); -+ } else { -+ TRACE_MGMT_DBG("Aborting all from tgt %p (mcmd %p)", -+ tgt, mcmd); -+ } -+ -+ mutex_lock(&scst_mutex); -+ -+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { -+ for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { -+ struct list_head *head = &sess->sess_tgt_dev_list[i]; -+ struct scst_tgt_dev *tgt_dev; -+ list_for_each_entry(tgt_dev, head, -+ sess_tgt_dev_list_entry) { -+ int rc; -+ -+ __scst_abort_task_set(mcmd, tgt_dev); -+ -+ if (mcmd->sess == tgt_dev->sess) { -+ rc = scst_call_dev_task_mgmt_fn( -+ mcmd, tgt_dev, 0); -+ if ((rc < 0) && -+ (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) -+ mcmd->status = rc; -+ } -+ -+ tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS or " -+ "ABORT ALL", 0); -+ } -+ } -+ } -+ -+ scst_unblock_aborted_cmds(1); -+ -+ mutex_unlock(&scst_mutex); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static int scst_abort_task(struct scst_mgmt_cmd *mcmd) -+{ -+ int res; -+ struct scst_cmd *cmd = mcmd->cmd_to_abort; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_MGMT_DBG("Aborting task (cmd %p, sn %d, set %d, tag %llu, " -+ "queue_type %x)", cmd, cmd->sn, cmd->sn_set, -+ (long long unsigned int)mcmd->tag, cmd->queue_type); -+ -+ if (mcmd->lun_set && (mcmd->lun != cmd->lun)) { -+ PRINT_ERROR("ABORT TASK: LUN mismatch: mcmd LUN %llx, " -+ "cmd LUN %llx, cmd tag %llu", -+ (long long unsigned int)mcmd->lun, -+ (long long unsigned int)cmd->lun, -+ (long long unsigned int)mcmd->tag); -+ mcmd->status = SCST_MGMT_STATUS_REJECTED; -+ } else if (mcmd->cmd_sn_set && -+ (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) || -+ (mcmd->cmd_sn == cmd->tgt_sn))) { -+ PRINT_ERROR("ABORT TASK: SN mismatch: mcmd SN %x, " -+ "cmd SN %x, cmd tag %llu", mcmd->cmd_sn, -+ cmd->tgt_sn, (long long unsigned int)mcmd->tag); -+ mcmd->status = SCST_MGMT_STATUS_REJECTED; -+ } else { -+ spin_lock_irq(&cmd->sess->sess_list_lock); -+ scst_abort_cmd(cmd, mcmd, 0, 1); -+ spin_unlock_irq(&cmd->sess->sess_list_lock); -+ -+ scst_unblock_aborted_cmds(0); -+ } -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ mcmd->cmd_to_abort = NULL; /* just in case */ -+ -+ __scst_cmd_put(cmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+/* Returns 0 if the command processing should be continued, <0 otherwise */ -+static int scst_mgmt_cmd_exec(struct scst_mgmt_cmd *mcmd) -+{ -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ mcmd->status = SCST_MGMT_STATUS_SUCCESS; -+ -+ switch (mcmd->fn) { -+ case SCST_ABORT_TASK: -+ res = scst_abort_task(mcmd); -+ break; -+ -+ case SCST_ABORT_TASK_SET: -+ case SCST_PR_ABORT_ALL: -+ res = scst_abort_task_set(mcmd); -+ break; -+ -+ case SCST_CLEAR_TASK_SET: -+ if (mcmd->mcmd_tgt_dev->dev->tst == -+ SCST_CONTR_MODE_SEP_TASK_SETS) -+ res = scst_abort_task_set(mcmd); -+ else -+ res = scst_clear_task_set(mcmd); -+ break; -+ -+ case SCST_LUN_RESET: -+ res = scst_lun_reset(mcmd); -+ break; -+ -+ case SCST_TARGET_RESET: -+ res = scst_target_reset(mcmd); -+ break; -+ -+ case SCST_ABORT_ALL_TASKS_SESS: -+ res = scst_abort_all_nexus_loss_sess(mcmd, 0); -+ break; -+ -+ case SCST_NEXUS_LOSS_SESS: -+ case SCST_UNREG_SESS_TM: -+ res = scst_abort_all_nexus_loss_sess(mcmd, 1); -+ break; -+ -+ case SCST_ABORT_ALL_TASKS: -+ res = scst_abort_all_nexus_loss_tgt(mcmd, 0); -+ break; -+ -+ case SCST_NEXUS_LOSS: -+ res = scst_abort_all_nexus_loss_tgt(mcmd, 1); -+ break; -+ -+ case SCST_CLEAR_ACA: -+ if (scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 1) == -+ SCST_DEV_TM_NOT_COMPLETED) { -+ mcmd->status = SCST_MGMT_STATUS_FN_NOT_SUPPORTED; -+ /* Nothing to do (yet) */ -+ } -+ goto out_done; -+ -+ default: -+ PRINT_ERROR("Unknown task management function %d", mcmd->fn); -+ mcmd->status = SCST_MGMT_STATUS_REJECTED; -+ goto out_done; -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_done: -+ res = scst_set_mcmd_next_state(mcmd); -+ goto out; -+} -+ -+static void scst_call_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd) -+{ -+ struct scst_session *sess = mcmd->sess; -+ -+ if ((sess->tgt->tgtt->task_mgmt_affected_cmds_done != NULL) && -+ (mcmd->fn != SCST_UNREG_SESS_TM) && -+ (mcmd->fn != SCST_PR_ABORT_ALL)) { -+ TRACE_DBG("Calling target %s task_mgmt_affected_cmds_done(%p)", -+ sess->tgt->tgtt->name, sess); -+ sess->tgt->tgtt->task_mgmt_affected_cmds_done(mcmd); -+ TRACE_MGMT_DBG("Target's %s task_mgmt_affected_cmds_done() " -+ "returned", sess->tgt->tgtt->name); -+ } -+ return; -+} -+ -+static int scst_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd) -+{ -+ int res; -+ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ switch (mcmd->fn) { -+ case SCST_NEXUS_LOSS_SESS: -+ case SCST_UNREG_SESS_TM: -+ scst_do_nexus_loss_sess(mcmd); -+ break; -+ -+ case SCST_NEXUS_LOSS: -+ scst_do_nexus_loss_tgt(mcmd); -+ break; -+ } -+ -+ mutex_unlock(&scst_mutex); -+ -+ scst_call_task_mgmt_affected_cmds_done(mcmd); -+ -+ res = scst_set_mcmd_next_state(mcmd); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd) -+{ -+ struct scst_device *dev; -+ struct scst_session *sess = mcmd->sess; -+ -+ TRACE_ENTRY(); -+ -+ mcmd->state = SCST_MCMD_STATE_FINISHED; -+ if (scst_is_strict_mgmt_fn(mcmd->fn) && (mcmd->completed_cmd_count > 0)) -+ mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST; -+ -+ if (mcmd->fn < SCST_UNREG_SESS_TM) -+ TRACE(TRACE_MGMT, "TM fn %d (%p) finished, " -+ "status %d", mcmd->fn, mcmd, mcmd->status); -+ else -+ TRACE_MGMT_DBG("TM fn %d (%p) finished, " -+ "status %d", mcmd->fn, mcmd, mcmd->status); -+ -+ if (mcmd->fn == SCST_PR_ABORT_ALL) { -+ mcmd->origin_pr_cmd->scst_cmd_done(mcmd->origin_pr_cmd, -+ SCST_CMD_STATE_DEFAULT, -+ SCST_CONTEXT_THREAD); -+ } else if ((sess->tgt->tgtt->task_mgmt_fn_done != NULL) && -+ (mcmd->fn != SCST_UNREG_SESS_TM)) { -+ TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)", -+ sess->tgt->tgtt->name, sess); -+ sess->tgt->tgtt->task_mgmt_fn_done(mcmd); -+ TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() " -+ "returned", sess->tgt->tgtt->name); -+ } -+ -+ if (mcmd->needs_unblocking) { -+ switch (mcmd->fn) { -+ case SCST_LUN_RESET: -+ case SCST_CLEAR_TASK_SET: -+ dev = mcmd->mcmd_tgt_dev->dev; -+ spin_lock_bh(&dev->dev_lock); -+ scst_unblock_dev(dev); -+ spin_unlock_bh(&dev->dev_lock); -+ break; -+ -+ case SCST_TARGET_RESET: -+ { -+ struct scst_acg *acg = mcmd->sess->acg; -+ struct scst_acg_dev *acg_dev; -+ -+ mutex_lock(&scst_mutex); -+ list_for_each_entry(acg_dev, &acg->acg_dev_list, -+ acg_dev_list_entry) { -+ dev = acg_dev->dev; -+ spin_lock_bh(&dev->dev_lock); -+ scst_unblock_dev(dev); -+ spin_unlock_bh(&dev->dev_lock); -+ } -+ mutex_unlock(&scst_mutex); -+ break; -+ } -+ -+ default: -+ BUG(); -+ break; -+ } -+ } -+ -+ mcmd->tgt_priv = NULL; -+ -+ TRACE_EXIT(); -+ return; -+} -+ -+/* Returns >0, if cmd should be requeued */ -+static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd) -+{ -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ /* -+ * We are in the TM thread and mcmd->state guaranteed to not be -+ * changed behind us. -+ */ -+ -+ TRACE_DBG("mcmd %p, state %d", mcmd, mcmd->state); -+ -+ while (1) { -+ switch (mcmd->state) { -+ case SCST_MCMD_STATE_INIT: -+ res = scst_mgmt_cmd_init(mcmd); -+ if (res != 0) -+ goto out; -+ break; -+ -+ case SCST_MCMD_STATE_EXEC: -+ if (scst_mgmt_cmd_exec(mcmd)) -+ goto out; -+ break; -+ -+ case SCST_MCMD_STATE_AFFECTED_CMDS_DONE: -+ if (scst_mgmt_affected_cmds_done(mcmd)) -+ goto out; -+ break; -+ -+ case SCST_MCMD_STATE_DONE: -+ scst_mgmt_cmd_send_done(mcmd); -+ break; -+ -+ case SCST_MCMD_STATE_FINISHED: -+ scst_free_mgmt_cmd(mcmd); -+ /* mcmd is dead */ -+ goto out; -+ -+ default: -+ PRINT_CRIT_ERROR("Wrong mcmd %p state %d (fn %d, " -+ "cmd_finish_wait_count %d, cmd_done_wait_count " -+ "%d)", mcmd, mcmd->state, mcmd->fn, -+ mcmd->cmd_finish_wait_count, -+ mcmd->cmd_done_wait_count); -+ BUG(); -+ res = -1; -+ goto out; -+ } -+ } -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+} -+ -+static inline int test_mgmt_cmd_list(void) -+{ -+ int res = !list_empty(&scst_active_mgmt_cmd_list) || -+ unlikely(kthread_should_stop()); -+ return res; -+} -+ -+int scst_tm_thread(void *arg) -+{ -+ TRACE_ENTRY(); -+ -+ PRINT_INFO("Task management thread started, PID %d", current->pid); -+ -+ current->flags |= PF_NOFREEZE; -+ -+ set_user_nice(current, -10); -+ -+ spin_lock_irq(&scst_mcmd_lock); -+ while (!kthread_should_stop()) { -+ wait_queue_t wait; -+ init_waitqueue_entry(&wait, current); -+ -+ if (!test_mgmt_cmd_list()) { -+ add_wait_queue_exclusive(&scst_mgmt_cmd_list_waitQ, -+ &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (test_mgmt_cmd_list()) -+ break; -+ spin_unlock_irq(&scst_mcmd_lock); -+ schedule(); -+ spin_lock_irq(&scst_mcmd_lock); -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&scst_mgmt_cmd_list_waitQ, &wait); -+ } -+ -+ while (!list_empty(&scst_active_mgmt_cmd_list)) { -+ int rc; -+ struct scst_mgmt_cmd *mcmd; -+ mcmd = list_entry(scst_active_mgmt_cmd_list.next, -+ typeof(*mcmd), mgmt_cmd_list_entry); -+ TRACE_MGMT_DBG("Deleting mgmt cmd %p from active cmd " -+ "list", mcmd); -+ list_del(&mcmd->mgmt_cmd_list_entry); -+ spin_unlock_irq(&scst_mcmd_lock); -+ rc = scst_process_mgmt_cmd(mcmd); -+ spin_lock_irq(&scst_mcmd_lock); -+ if (rc > 0) { -+ if (test_bit(SCST_FLAG_SUSPENDED, &scst_flags) && -+ !test_bit(SCST_FLAG_SUSPENDING, -+ &scst_flags)) { -+ TRACE_MGMT_DBG("Adding mgmt cmd %p to " -+ "head of delayed mgmt cmd list", -+ mcmd); -+ list_add(&mcmd->mgmt_cmd_list_entry, -+ &scst_delayed_mgmt_cmd_list); -+ } else { -+ TRACE_MGMT_DBG("Adding mgmt cmd %p to " -+ "head of active mgmt cmd list", -+ mcmd); -+ list_add(&mcmd->mgmt_cmd_list_entry, -+ &scst_active_mgmt_cmd_list); -+ } -+ } -+ } -+ } -+ spin_unlock_irq(&scst_mcmd_lock); -+ -+ /* -+ * If kthread_should_stop() is true, we are guaranteed to be -+ * on the module unload, so scst_active_mgmt_cmd_list must be empty. -+ */ -+ BUG_ON(!list_empty(&scst_active_mgmt_cmd_list)); -+ -+ PRINT_INFO("Task management thread PID %d finished", current->pid); -+ -+ TRACE_EXIT(); -+ return 0; -+} -+ -+static struct scst_mgmt_cmd *scst_pre_rx_mgmt_cmd(struct scst_session -+ *sess, int fn, int atomic, void *tgt_priv) -+{ -+ struct scst_mgmt_cmd *mcmd = NULL; -+ -+ TRACE_ENTRY(); -+ -+ if (unlikely(sess->tgt->tgtt->task_mgmt_fn_done == NULL)) { -+ PRINT_ERROR("New mgmt cmd, but task_mgmt_fn_done() is NULL " -+ "(target %s)", sess->tgt->tgtt->name); -+ goto out; -+ } -+ -+ mcmd = scst_alloc_mgmt_cmd(atomic ? GFP_ATOMIC : GFP_KERNEL); -+ if (mcmd == NULL) { -+ PRINT_CRIT_ERROR("Lost TM fn %d, initiator %s", fn, -+ sess->initiator_name); -+ goto out; -+ } -+ -+ mcmd->sess = sess; -+ mcmd->fn = fn; -+ mcmd->state = SCST_MCMD_STATE_INIT; -+ mcmd->tgt_priv = tgt_priv; -+ -+ if (fn == SCST_PR_ABORT_ALL) { -+ atomic_inc(&mcmd->origin_pr_cmd->pr_abort_counter->pr_abort_pending_cnt); -+ atomic_inc(&mcmd->origin_pr_cmd->pr_abort_counter->pr_aborting_cnt); -+ } -+ -+out: -+ TRACE_EXIT(); -+ return mcmd; -+} -+ -+static int scst_post_rx_mgmt_cmd(struct scst_session *sess, -+ struct scst_mgmt_cmd *mcmd) -+{ -+ unsigned long flags; -+ int res = 0; -+ -+ TRACE_ENTRY(); -+ -+ scst_sess_get(sess); -+ -+ if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) { -+ PRINT_CRIT_ERROR("New mgmt cmd while shutting down the " -+ "session %p shut_phase %ld", sess, sess->shut_phase); -+ BUG(); -+ } -+ -+ local_irq_save(flags); -+ -+ spin_lock(&sess->sess_list_lock); -+ atomic_inc(&sess->sess_cmd_count); -+ -+ if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) { -+ switch (sess->init_phase) { -+ case SCST_SESS_IPH_INITING: -+ TRACE_DBG("Adding mcmd %p to init deferred mcmd list", -+ mcmd); -+ list_add_tail(&mcmd->mgmt_cmd_list_entry, -+ &sess->init_deferred_mcmd_list); -+ goto out_unlock; -+ case SCST_SESS_IPH_SUCCESS: -+ break; -+ case SCST_SESS_IPH_FAILED: -+ res = -1; -+ goto out_unlock; -+ default: -+ BUG(); -+ } -+ } -+ -+ spin_unlock(&sess->sess_list_lock); -+ -+ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd list", mcmd); -+ spin_lock(&scst_mcmd_lock); -+ list_add_tail(&mcmd->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list); -+ spin_unlock(&scst_mcmd_lock); -+ -+ local_irq_restore(flags); -+ -+ wake_up(&scst_mgmt_cmd_list_waitQ); -+ -+out: -+ TRACE_EXIT(); -+ return res; -+ -+out_unlock: -+ spin_unlock(&sess->sess_list_lock); -+ local_irq_restore(flags); -+ goto out; -+} -+ -+/** -+ * scst_rx_mgmt_fn() - create new management command and send it for execution -+ * -+ * Description: -+ * Creates new management command and sends it for execution. -+ * -+ * Returns 0 for success, error code otherwise. -+ * -+ * Must not be called in parallel with scst_unregister_session() for the -+ * same sess. -+ */ -+int scst_rx_mgmt_fn(struct scst_session *sess, -+ const struct scst_rx_mgmt_params *params) -+{ -+ int res = -EFAULT; -+ struct scst_mgmt_cmd *mcmd = NULL; -+ -+ TRACE_ENTRY(); -+ -+ switch (params->fn) { -+ case SCST_ABORT_TASK: -+ BUG_ON(!params->tag_set); -+ break; -+ case SCST_TARGET_RESET: -+ case SCST_ABORT_ALL_TASKS: -+ case SCST_NEXUS_LOSS: -+ break; -+ default: -+ BUG_ON(!params->lun_set); -+ } -+ -+ mcmd = scst_pre_rx_mgmt_cmd(sess, params->fn, params->atomic, -+ params->tgt_priv); -+ if (mcmd == NULL) -+ goto out; -+ -+ if (params->lun_set) { -+ mcmd->lun = scst_unpack_lun(params->lun, params->lun_len); -+ if (mcmd->lun == NO_SUCH_LUN) -+ goto out_free; -+ mcmd->lun_set = 1; -+ } -+ -+ if (params->tag_set) -+ mcmd->tag = params->tag; -+ -+ mcmd->cmd_sn_set = params->cmd_sn_set; -+ mcmd->cmd_sn = params->cmd_sn; -+ -+ if (params->fn < SCST_UNREG_SESS_TM) -+ TRACE(TRACE_MGMT, "TM fn %d (%p)", params->fn, mcmd); -+ else -+ TRACE_MGMT_DBG("TM fn %d (%p)", params->fn, mcmd); -+ -+ TRACE_MGMT_DBG("sess=%p, tag_set %d, tag %lld, lun_set %d, " -+ "lun=%lld, cmd_sn_set %d, cmd_sn %d, priv %p", sess, -+ params->tag_set, -+ (long long unsigned int)params->tag, -+ params->lun_set, -+ (long long unsigned int)mcmd->lun, -+ params->cmd_sn_set, -+ params->cmd_sn, -+ params->tgt_priv); -+ -+ if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0) -+ goto out_free; -+ -+ res = 0; -+ -+out: -+ TRACE_EXIT_RES(res); -+ return res; -+ -+out_free: -+ scst_free_mgmt_cmd(mcmd); -+ mcmd = NULL; -+ goto out; -+} -+EXPORT_SYMBOL(scst_rx_mgmt_fn); -+ -+/* -+ * Written by Jack Handy - jakkhandy@hotmail.com -+ * Taken by Gennadiy Nerubayev <parakie@gmail.com> from -+ * http://www.codeproject.com/KB/string/wildcmp.aspx. No license attached -+ * to it, and it's posted on a free site; assumed to be free for use. -+ * -+ * Added the negative sign support - VLNB -+ * -+ * Also see comment for wildcmp(). -+ * -+ * User space part of iSCSI-SCST also has a copy of this code, so fixing a bug -+ * here, don't forget to fix the copy too! -+ */ -+static bool __wildcmp(const char *wild, const char *string, int recursion_level) -+{ -+ const char *cp = NULL, *mp = NULL; -+ -+ while ((*string) && (*wild != '*')) { -+ if ((*wild == '!') && (recursion_level == 0)) -+ return !__wildcmp(++wild, string, ++recursion_level); -+ -+ if ((*wild != *string) && (*wild != '?')) -+ return false; -+ -+ wild++; -+ string++; -+ } -+ -+ while (*string) { -+ if ((*wild == '!') && (recursion_level == 0)) -+ return !__wildcmp(++wild, string, ++recursion_level); -+ -+ if (*wild == '*') { -+ if (!*++wild) -+ return true; -+ -+ mp = wild; -+ cp = string+1; -+ } else if ((*wild == *string) || (*wild == '?')) { -+ wild++; -+ string++; -+ } else { -+ wild = mp; -+ string = cp++; -+ } -+ } -+ -+ while (*wild == '*') -+ wild++; -+ -+ return !*wild; -+} -+ -+/* -+ * Returns true if string "string" matches pattern "wild", false otherwise. -+ * Pattern is a regular DOS-type pattern, containing '*' and '?' symbols. -+ * '*' means match all any symbols, '?' means match only any single symbol. -+ * -+ * For instance: -+ * if (wildcmp("bl?h.*", "blah.jpg")) { -+ * // match -+ * } else { -+ * // no match -+ * } -+ * -+ * Also it supports boolean inversion sign '!', which does boolean inversion of -+ * the value of the rest of the string. Only one '!' allowed in the pattern, -+ * other '!' are treated as regular symbols. For instance: -+ * if (wildcmp("bl!?h.*", "blah.jpg")) { -+ * // no match -+ * } else { -+ * // match -+ * } -+ * -+ * Also see comment for __wildcmp(). -+ */ -+static bool wildcmp(const char *wild, const char *string) -+{ -+ return __wildcmp(wild, string, 0); -+} -+ -+/* scst_mutex supposed to be held */ -+static struct scst_acg *scst_find_tgt_acg_by_name_wild(struct scst_tgt *tgt, -+ const char *initiator_name) -+{ -+ struct scst_acg *acg, *res = NULL; -+ struct scst_acn *n; -+ -+ TRACE_ENTRY(); -+ -+ if (initiator_name == NULL) -+ goto out; -+ -+ list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) { -+ list_for_each_entry(n, &acg->acn_list, acn_list_entry) { -+ if (wildcmp(n->name, initiator_name)) { -+ TRACE_DBG("Access control group %s found", -+ acg->acg_name); -+ res = acg; -+ goto out; -+ } -+ } -+ } -+ -+out: -+ TRACE_EXIT_HRES(res); -+ return res; -+} -+ -+/* Must be called under scst_mutex */ -+static struct scst_acg *__scst_find_acg(struct scst_tgt *tgt, -+ const char *initiator_name) -+{ -+ struct scst_acg *acg = NULL; -+ -+ TRACE_ENTRY(); -+ -+ acg = scst_find_tgt_acg_by_name_wild(tgt, initiator_name); -+ if (acg == NULL) -+ acg = tgt->default_acg; -+ -+ TRACE_EXIT_HRES((unsigned long)acg); -+ return acg; -+} -+ -+/* Must be called under scst_mutex */ -+struct scst_acg *scst_find_acg(const struct scst_session *sess) -+{ -+ return __scst_find_acg(sess->tgt, sess->initiator_name); -+} -+ -+/** -+ * scst_initiator_has_luns() - check if this initiator will see any LUNs -+ * -+ * Checks if this initiator will see any LUNs upon connect to this target. -+ * Returns true if yes and false otherwise. -+ */ -+bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name) -+{ -+ bool res; -+ struct scst_acg *acg; -+ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ acg = __scst_find_acg(tgt, initiator_name); -+ -+ res = !list_empty(&acg->acg_dev_list); -+ -+ mutex_unlock(&scst_mutex); -+ -+ TRACE_EXIT_RES(res); -+ return res; -+} -+EXPORT_SYMBOL_GPL(scst_initiator_has_luns); -+ -+static int scst_init_session(struct scst_session *sess) -+{ -+ int res = 0; -+ struct scst_cmd *cmd; -+ struct scst_mgmt_cmd *mcmd, *tm; -+ int mwake = 0; -+ -+ TRACE_ENTRY(); -+ -+ mutex_lock(&scst_mutex); -+ -+ sess->acg = scst_find_acg(sess); -+ -+ PRINT_INFO("Using security group \"%s\" for initiator \"%s\" " -+ "(target %s)", sess->acg->acg_name, sess->initiator_name, -+ sess->tgt->tgt_name); -+ -+ list_add_tail(&sess->acg_sess_list_entry, &sess->acg->acg_sess_list); -+ -+ TRACE_DBG("Adding sess %p to tgt->sess_list", sess); -+ list_add_tail(&sess->sess_list_entry, &sess->tgt->sess_list); -+ -+ if (sess->tgt->tgtt->get_initiator_port_transport_id != NULL) { -+ res = sess->tgt->tgtt->get_initiator_port_transport_id( -+ sess->tgt, sess, &sess->transport_id); -+ if (res != 0) { -+ PRINT_ERROR("Unable to make initiator %s port " -+ "transport id", sess->initiator_name); -+ goto failed; -+ } -+ TRACE_PR("sess %p (ini %s), transport id %s/%d", sess, -+ sess->initiator_name, -+ debug_transport_id_to_initiator_name( -+ sess->transport_id), sess->tgt->rel_tgt_id); -+ } -+ -+ res = scst_sess_sysfs_create(sess); -+ if (res != 0) -+ goto failed; -+ -+ /* -+ * scst_sess_alloc_tgt_devs() must be called after session added in the -+ * sess_list to not race with scst_check_reassign_sess()! -+ */ -+ res = scst_sess_alloc_tgt_devs(sess); -+ -+failed: -+ mutex_unlock(&scst_mutex); -+ -+ if (sess->init_result_fn) { -+ TRACE_DBG("Calling init_result_fn(%p)", sess); -+ sess->init_result_fn(sess, sess->reg_sess_data, res); -+ TRACE_DBG("%s", "init_result_fn() returned"); -+ } -+ -+ spin_lock_irq(&sess->sess_list_lock); -+ -+ if (res == 0) -+ sess->init_phase = SCST_SESS_IPH_SUCCESS; -+ else -+ sess->init_phase = SCST_SESS_IPH_FAILED; -+ -+restart: -+ list_for_each_entry(cmd, &sess->init_deferred_cmd_list, -+ cmd_list_entry) { -+ TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd); -+ list_del(&cmd->cmd_list_entry); -+ atomic_dec(&sess->sess_cmd_count); -+ spin_unlock_irq(&sess->sess_list_lock); -+ scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD); -+ spin_lock_irq(&sess->sess_list_lock); -+ goto restart; -+ } -+ -+ spin_lock(&scst_mcmd_lock); -+ list_for_each_entry_safe(mcmd, tm, &sess->init_deferred_mcmd_list, -+ mgmt_cmd_list_entry) { -+ TRACE_DBG("Moving mgmt command %p from init deferred mcmd list", -+ mcmd); -+ list_move_tail(&mcmd->mgmt_cmd_list_entry, -+ &scst_active_mgmt_cmd_list); -+ mwake = 1; -+ } -+ -+ spin_unlock(&scst_mcmd_lock); -+ /* -+ * In case of an error at this point the caller target driver supposed -+ * to already call this sess's unregistration. -+ */ -+ sess->init_phase = SCST_SESS_IPH_READY; -+ spin_unlock_irq(&sess->sess_list_lock); -+ -+ if (mwake) -+ wake_up(&scst_mgmt_cmd_list_waitQ); -+ -+ scst_sess_put(sess); -+ -+ TRACE_EXIT(); -+ return res; -+} -+ -+/** -+ * scst_register_session() - register session -+ * @tgt: target -+ * @atomic: true, if the function called in the atomic context. If false, -+ * this function will block until the session registration is -+ * completed. -+ * @initiator_name: remote initiator's name, any NULL-terminated string, -+ * e.g. iSCSI name, which used as the key to found appropriate -+ * access control group. Could be NULL, then the default -+ * target's LUNs are used. -+ * @tgt_priv: pointer to target driver's private data -+ * @result_fn_data: any target driver supplied data -+ * @result_fn: pointer to the function that will be asynchronously called -+ * when session initialization finishes. -+ * Can be NULL. Parameters: -+ * - sess - session -+ * - data - target driver supplied to scst_register_session() -+ * data -+ * - result - session initialization result, 0 on success or -+ * appropriate error code otherwise -+ * -+ * Description: -+ * Registers new session. Returns new session on success or NULL otherwise. -+ * -+ * Note: A session creation and initialization is a complex task, -+ * which requires sleeping state, so it can't be fully done -+ * in interrupt context. Therefore the "bottom half" of it, if -+ * scst_register_session() is called from atomic context, will be -+ * done in SCST thread context. In this case scst_register_session() -+ * will return not completely initialized session, but the target -+ * driver can supply commands to this session via scst_rx_cmd(). -+ * Those commands processing will be delayed inside SCST until -+ * the session initialization is finished, then their processing -+ * will be restarted. The target driver will be notified about -+ * finish of the session initialization by function result_fn(). -+ * On success the target driver could do nothing, but if the -+ * initialization fails, the target driver must ensure that -+ * no more new commands being sent or will be sent to SCST after -+ * result_fn() returns. All already sent to SCST commands for -+ * failed session will be returned in xmit_response() with BUSY status. -+ * In case of failure the driver shall call scst_unregister_session() -+ * inside result_fn(), it will NOT be called automatically. -+ */ -+struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic, -+ const char *initiator_name, void *tgt_priv, void *result_fn_data, -+ void (*result_fn) (struct scst_session *sess, void *data, int result)) -+{ -+ struct scst_session *sess; -+ int res; -+ unsigned long flags; -+ -+ TRACE_ENTRY(); -+ -+ sess = scst_alloc_session(tgt, atomic ? GFP_ATOMIC : GFP_KERNEL, -+ initiator_name); -+ if (sess == NULL) -+ goto out; -+ -+ scst_sess_set_tgt_priv(sess, tgt_priv); -+ -+ scst_sess_get(sess); /* one for registered session */ -+ scst_sess_get(sess); /* one held until sess is inited */ -+ -+ if (atomic) { -+ sess->reg_sess_data = result_fn_data; -+ sess->init_result_fn = result_fn; -+ spin_lock_irqsave(&scst_mgmt_lock, flags); -+ TRACE_DBG("Adding sess %p to scst_sess_init_list", sess); -+ list_add_tail(&sess->sess_init_list_entry, -+ &scst_sess_init_list); -+ spin_unlock_irqrestore(&scst_mgmt_lock, flags); -+ wake_up(&scst_mgmt_waitQ); -+ } else { -+ res = scst_init_session(sess); -+ if (res != 0) -+ goto out_free; -+ } -+ -+out: -+ TRACE_EXIT(); -+ return sess; -+ -+out_free: -+ scst_free_session(sess); -+ sess = NULL; -+ goto out; -+} -+EXPORT_SYMBOL_GPL(scst_register_session); -+ -+/** -+ * scst_register_session_non_gpl() - register session (non-GPL version) -+ * @tgt: target -+ * @initiator_name: remote initiator's name, any NULL-terminated string, -+ * e.g. iSCSI name, which used as the key to found appropriate -+ * access control group. Could be NULL, then the default -+ * target's LUNs are used. -+ * @tgt_priv: pointer to target driver's private data -+ * -+ * Description: -+ * Registers new session. Returns new session on success or NULL otherwise. -+ */ -+struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt, -+ const char *initiator_name, void *tgt_priv) -+{ -+ return scst_register_session(tgt, 0, initiator_name, tgt_priv, -+ NULL, NULL); -+} -+EXPORT_SYMBOL(scst_register_session_non_gpl); -+ -+/** -+ * scst_unregister_session() - unregister session -+ * @sess: session to be unregistered -+ * @wait: if true, instructs to wait until all commands, which -+ * currently is being executed and belonged to the session, -+ * finished. Otherwise, target driver should be prepared to -+ * receive xmit_response() for the session's command after -+ * scst_unregister_session() returns. -+ * @unreg_done_fn: pointer to the function that will be asynchronously called -+ * when the last session's command finishes and -+ * the session is about to be completely freed. Can be NULL. -+ * Parameter: -+ * - sess - session -+ * -+ * Unregisters session. -+ * -+ * Notes: -+ * - All outstanding commands will be finished regularly. After -+ * scst_unregister_session() returned, no new commands must be sent to -+ * SCST via scst_rx_cmd(). -+ * -+ * - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is -+ * called in parallel with scst_unregister_session(). -+ * -+ * - Can be called before result_fn() of scst_register_session() called, -+ * i.e. during the session registration/initialization. -+ * -+ * - It is highly recommended to call scst_unregister_session() as soon as it -+ * gets clear that session will be unregistered and not to wait until all -+ * related commands finished. This function provides the wait functionality, -+ * but it also starts recovering stuck commands, if there are any. -+ * Otherwise, your target driver could wait for those commands forever. -+ */ -+void scst_unregister_session(struct scst_session *sess, int wait, -+ void (*unreg_done_fn) (struct scst_session *sess)) -+{ -+ unsigned long flags; -+ DECLARE_COMPLETION_ONSTACK(c); -+ int rc, lun; -+ -+ TRACE_ENTRY(); -+ -+ TRACE_MGMT_DBG("Unregistering session %p (wait %d)", sess, wait); -+ -+ sess->unreg_done_fn = unreg_done_fn; -+ -+ /* Abort all outstanding commands and clear reservation, if necessary */ -+ lun = 0; -+ rc = scst_rx_mgmt_fn_lun(sess, SCST_UNREG_SESS_TM, -+ (uint8_t *)&lun, sizeof(lun), SCST_ATOMIC, NULL); -+ if (rc != 0) { -+ PRINT_ERROR("SCST_UNREG_SESS_TM failed %d (sess %p)", -+ rc, sess); -+ } -+ -+ sess->shut_phase = SCST_SESS_SPH_SHUTDOWN; -+ -+ spin_lock_irqsave(&scst_mgmt_lock, flags); -+ -+ if (wait) -+ sess->shutdown_compl = &c; -+ -+ spin_unlock_irqrestore(&scst_mgmt_lock, flags); -+ -+ scst_sess_put(sess); -+ -+ if (wait) { -+ TRACE_DBG("Waiting for session %p to complete", sess); -+ wait_for_completion(&c); -+ } -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL_GPL(scst_unregister_session); -+ -+/** -+ * scst_unregister_session_non_gpl() - unregister session, non-GPL version -+ * @sess: session to be unregistered -+ * -+ * Unregisters session. -+ * -+ * See notes for scst_unregister_session() above. -+ */ -+void scst_unregister_session_non_gpl(struct scst_session *sess) -+{ -+ TRACE_ENTRY(); -+ -+ scst_unregister_session(sess, 1, NULL); -+ -+ TRACE_EXIT(); -+ return; -+} -+EXPORT_SYMBOL(scst_unregister_session_non_gpl); -+ -+static inline int test_mgmt_list(void) -+{ -+ int res = !list_empty(&scst_sess_init_list) || -+ !list_empty(&scst_sess_shut_list) || -+ unlikely(kthread_should_stop()); -+ return res; -+} -+ -+int scst_global_mgmt_thread(void *arg) -+{ -+ struct scst_session *sess; -+ -+ TRACE_ENTRY(); -+ -+ PRINT_INFO("Management thread started, PID %d", current->pid); -+ -+ current->flags |= PF_NOFREEZE; -+ -+ set_user_nice(current, -10); -+ -+ spin_lock_irq(&scst_mgmt_lock); -+ while (!kthread_should_stop()) { -+ wait_queue_t wait; -+ init_waitqueue_entry(&wait, current); -+ -+ if (!test_mgmt_list()) { -+ add_wait_queue_exclusive(&scst_mgmt_waitQ, &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (test_mgmt_list()) -+ break; -+ spin_unlock_irq(&scst_mgmt_lock); -+ schedule(); -+ spin_lock_irq(&scst_mgmt_lock); -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&scst_mgmt_waitQ, &wait); -+ } -+ -+ while (!list_empty(&scst_sess_init_list)) { -+ sess = list_entry(scst_sess_init_list.next, -+ typeof(*sess), sess_init_list_entry); -+ TRACE_DBG("Removing sess %p from scst_sess_init_list", -+ sess); -+ list_del(&sess->sess_init_list_entry); -+ spin_unlock_irq(&scst_mgmt_lock); -+ -+ if (sess->init_phase == SCST_SESS_IPH_INITING) -+ scst_init_session(sess); -+ else { -+ PRINT_CRIT_ERROR("session %p is in " -+ "scst_sess_init_list, but in unknown " -+ "init phase %x", sess, -+ sess->init_phase); -+ BUG(); -+ } -+ -+ spin_lock_irq(&scst_mgmt_lock); -+ } -+ -+ while (!list_empty(&scst_sess_shut_list)) { -+ sess = list_entry(scst_sess_shut_list.next, -+ typeof(*sess), sess_shut_list_entry); -+ TRACE_DBG("Removing sess %p from scst_sess_shut_list", -+ sess); -+ list_del(&sess->sess_shut_list_entry); -+ spin_unlock_irq(&scst_mgmt_lock); -+ -+ switch (sess->shut_phase) { -+ case SCST_SESS_SPH_SHUTDOWN: -+ BUG_ON(atomic_read(&sess->refcnt) != 0); -+ scst_free_session_callback(sess); -+ break; -+ default: -+ PRINT_CRIT_ERROR("session %p is in " -+ "scst_sess_shut_list, but in unknown " -+ "shut phase %lx", sess, -+ sess->shut_phase); -+ BUG(); -+ break; -+ } -+ -+ spin_lock_irq(&scst_mgmt_lock); -+ } -+ } -+ spin_unlock_irq(&scst_mgmt_lock); -+ -+ /* -+ * If kthread_should_stop() is true, we are guaranteed to be -+ * on the module unload, so both lists must be empty. -+ */ -+ BUG_ON(!list_empty(&scst_sess_init_list)); -+ BUG_ON(!list_empty(&scst_sess_shut_list)); -+ -+ PRINT_INFO("Management thread PID %d finished", current->pid); -+ -+ TRACE_EXIT(); -+ return 0; -+} -+ -+/* Called under sess->sess_list_lock */ -+static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, -+ uint64_t tag, bool to_abort) -+{ -+ struct scst_cmd *cmd, *res = NULL; -+ -+ TRACE_ENTRY(); -+ -+ /* ToDo: hash list */ -+ -+ TRACE_DBG("%s (sess=%p, tag=%llu)", "Searching in sess cmd list", -+ sess, (long long unsigned int)tag); -+ -+ list_for_each_entry(cmd, &sess->sess_cmd_list, -+ sess_cmd_list_entry) { -+ if (cmd->tag == tag) { -+ /* -+ * We must not count done commands, because -+ * they were submitted for transmission. -+ * Otherwise we can have a race, when for -+ * some reason cmd's release delayed -+ * after transmission and initiator sends -+ * cmd with the same tag => it can be possible -+ * that a wrong cmd will be returned. -+ */ -+ if (cmd->done) { -+ if (to_abort) { -+ /* -+ * We should return the latest not -+ * aborted cmd with this tag. -+ */ -+ if (res == NULL) -+ res = cmd; -+ else { -+ if (test_bit(SCST_CMD_ABORTED, -+ &res->cmd_flags)) { -+ res = cmd; -+ } else if (!test_bit(SCST_CMD_ABORTED, -+ &cmd->cmd_flags)) -+ res = cmd; -+ } -+ } -+ continue; -+ } else { -+ res = cmd; -+ break; -+ } -+ } -+ } -+ -+ TRACE_EXIT(); -+ return res; -+} -+ -+/** -+ * scst_find_cmd() - find command by custom comparison function -+ * -+ * Finds a command based on user supplied data and comparison -+ * callback function, that should return true, if the command is found. -+ * Returns the command on success or NULL otherwise. -+ */ -+struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data, -+ int (*cmp_fn) (struct scst_cmd *cmd, -+ void *data)) -+{ -+ struct scst_cmd *cmd = NULL; -+ unsigned long flags = 0; -+ -+ TRACE_ENTRY(); -+ -+ if (cmp_fn == NULL) -+ goto out; -+ -+ spin_lock_irqsave(&sess->sess_list_lock, flags); -+ -+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess); -+ list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list_entry) { -+ /* -+ * We must not count done commands, because they were -+ * submitted for transmission. Otherwise we can have a race, -+ * when for some reason cmd's release delayed after -+ * transmission and initiator sends cmd with the same tag => -+ * it can be possible that a wrong cmd will be returned. -+ */ -+ if (cmd->done) -+ continue; -+ if (cmp_fn(cmd, data)) -+ goto out_unlock; -+ } -+ -+ cmd = NULL; -+ -+out_unlock: -+ spin_unlock_irqrestore(&sess->sess_list_lock, flags); -+ -+out: -+ TRACE_EXIT(); -+ return cmd; -+} -+EXPORT_SYMBOL(scst_find_cmd); -+ -+/** |