aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-02-11 04:37:32 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-02-11 04:37:40 -0500
commit95ec807e0a42188ec1ce29cf939816ad1e22f2d3 (patch)
tree3baf358d6b74047cf26e581bdfa9807959b473c3 /arch
parent48cae885d5a896030588978f503c73c5ed5e62b1 (diff)
[S390] Update default configuration.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/defconfig87
1 files changed, 60 insertions, 27 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index a0e748da9909..31e809c77790 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.28-rc6 3# Linux kernel version: 2.6.29-rc4
4# Thu Nov 27 11:00:49 2008 4# Wed Feb 11 10:07:16 2009
5# 5#
6CONFIG_SCHED_MC=y 6CONFIG_SCHED_MC=y
7CONFIG_MMU=y 7CONFIG_MMU=y
@@ -14,12 +14,14 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
14# CONFIG_ARCH_HAS_ILOG2_U64 is not set 14# CONFIG_ARCH_HAS_ILOG2_U64 is not set
15CONFIG_GENERIC_HWEIGHT=y 15CONFIG_GENERIC_HWEIGHT=y
16CONFIG_GENERIC_TIME=y 16CONFIG_GENERIC_TIME=y
17CONFIG_GENERIC_TIME_VSYSCALL=y
17CONFIG_GENERIC_CLOCKEVENTS=y 18CONFIG_GENERIC_CLOCKEVENTS=y
18CONFIG_GENERIC_BUG=y 19CONFIG_GENERIC_BUG=y
19CONFIG_NO_IOMEM=y 20CONFIG_NO_IOMEM=y
20CONFIG_NO_DMA=y 21CONFIG_NO_DMA=y
21CONFIG_GENERIC_LOCKBREAK=y 22CONFIG_GENERIC_LOCKBREAK=y
22CONFIG_PGSTE=y 23CONFIG_PGSTE=y
24CONFIG_VIRT_CPU_ACCOUNTING=y
23CONFIG_S390=y 25CONFIG_S390=y
24CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" 26CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
25 27
@@ -39,20 +41,29 @@ CONFIG_POSIX_MQUEUE=y
39# CONFIG_TASKSTATS is not set 41# CONFIG_TASKSTATS is not set
40CONFIG_AUDIT=y 42CONFIG_AUDIT=y
41# CONFIG_AUDITSYSCALL is not set 43# CONFIG_AUDITSYSCALL is not set
44
45#
46# RCU Subsystem
47#
48CONFIG_CLASSIC_RCU=y
49# CONFIG_TREE_RCU is not set
50# CONFIG_PREEMPT_RCU is not set
51# CONFIG_TREE_RCU_TRACE is not set
52# CONFIG_PREEMPT_RCU_TRACE is not set
42CONFIG_IKCONFIG=y 53CONFIG_IKCONFIG=y
43CONFIG_IKCONFIG_PROC=y 54CONFIG_IKCONFIG_PROC=y
44CONFIG_LOG_BUF_SHIFT=17 55CONFIG_LOG_BUF_SHIFT=17
56CONFIG_GROUP_SCHED=y
57CONFIG_FAIR_GROUP_SCHED=y
58# CONFIG_RT_GROUP_SCHED is not set
59CONFIG_USER_SCHED=y
60# CONFIG_CGROUP_SCHED is not set
45CONFIG_CGROUPS=y 61CONFIG_CGROUPS=y
46# CONFIG_CGROUP_DEBUG is not set 62# CONFIG_CGROUP_DEBUG is not set
47CONFIG_CGROUP_NS=y 63CONFIG_CGROUP_NS=y
48# CONFIG_CGROUP_FREEZER is not set 64# CONFIG_CGROUP_FREEZER is not set
49# CONFIG_CGROUP_DEVICE is not set 65# CONFIG_CGROUP_DEVICE is not set
50# CONFIG_CPUSETS is not set 66# CONFIG_CPUSETS is not set
51CONFIG_GROUP_SCHED=y
52CONFIG_FAIR_GROUP_SCHED=y
53# CONFIG_RT_GROUP_SCHED is not set
54CONFIG_USER_SCHED=y
55# CONFIG_CGROUP_SCHED is not set
56# CONFIG_CGROUP_CPUACCT is not set 67# CONFIG_CGROUP_CPUACCT is not set
57# CONFIG_RESOURCE_COUNTERS is not set 68# CONFIG_RESOURCE_COUNTERS is not set
58CONFIG_SYSFS_DEPRECATED=y 69CONFIG_SYSFS_DEPRECATED=y
@@ -63,6 +74,7 @@ CONFIG_UTS_NS=y
63CONFIG_IPC_NS=y 74CONFIG_IPC_NS=y
64# CONFIG_USER_NS is not set 75# CONFIG_USER_NS is not set
65# CONFIG_PID_NS is not set 76# CONFIG_PID_NS is not set
77# CONFIG_NET_NS is not set
66CONFIG_BLK_DEV_INITRD=y 78CONFIG_BLK_DEV_INITRD=y
67CONFIG_INITRAMFS_SOURCE="" 79CONFIG_INITRAMFS_SOURCE=""
68# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 80# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -91,17 +103,17 @@ CONFIG_SLAB=y
91# CONFIG_SLUB is not set 103# CONFIG_SLUB is not set
92# CONFIG_SLOB is not set 104# CONFIG_SLOB is not set
93# CONFIG_PROFILING is not set 105# CONFIG_PROFILING is not set
94# CONFIG_MARKERS is not set
95CONFIG_HAVE_OPROFILE=y 106CONFIG_HAVE_OPROFILE=y
96CONFIG_KPROBES=y 107CONFIG_KPROBES=y
108CONFIG_HAVE_SYSCALL_WRAPPERS=y
97CONFIG_KRETPROBES=y 109CONFIG_KRETPROBES=y
98CONFIG_HAVE_KPROBES=y 110CONFIG_HAVE_KPROBES=y
99CONFIG_HAVE_KRETPROBES=y 111CONFIG_HAVE_KRETPROBES=y
100CONFIG_HAVE_ARCH_TRACEHOOK=y 112CONFIG_HAVE_ARCH_TRACEHOOK=y
113CONFIG_USE_GENERIC_SMP_HELPERS=y
101# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set 114# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
102CONFIG_SLABINFO=y 115CONFIG_SLABINFO=y
103CONFIG_RT_MUTEXES=y 116CONFIG_RT_MUTEXES=y
104# CONFIG_TINY_SHMEM is not set
105CONFIG_BASE_SMALL=0 117CONFIG_BASE_SMALL=0
106CONFIG_MODULES=y 118CONFIG_MODULES=y
107# CONFIG_MODULE_FORCE_LOAD is not set 119# CONFIG_MODULE_FORCE_LOAD is not set
@@ -109,7 +121,7 @@ CONFIG_MODULE_UNLOAD=y
109# CONFIG_MODULE_FORCE_UNLOAD is not set 121# CONFIG_MODULE_FORCE_UNLOAD is not set
110CONFIG_MODVERSIONS=y 122CONFIG_MODVERSIONS=y
111# CONFIG_MODULE_SRCVERSION_ALL is not set 123# CONFIG_MODULE_SRCVERSION_ALL is not set
112CONFIG_KMOD=y 124CONFIG_INIT_ALL_POSSIBLE=y
113CONFIG_STOP_MACHINE=y 125CONFIG_STOP_MACHINE=y
114CONFIG_BLOCK=y 126CONFIG_BLOCK=y
115# CONFIG_BLK_DEV_IO_TRACE is not set 127# CONFIG_BLK_DEV_IO_TRACE is not set
@@ -130,7 +142,6 @@ CONFIG_DEFAULT_DEADLINE=y
130# CONFIG_DEFAULT_NOOP is not set 142# CONFIG_DEFAULT_NOOP is not set
131CONFIG_DEFAULT_IOSCHED="deadline" 143CONFIG_DEFAULT_IOSCHED="deadline"
132CONFIG_PREEMPT_NOTIFIERS=y 144CONFIG_PREEMPT_NOTIFIERS=y
133CONFIG_CLASSIC_RCU=y
134# CONFIG_FREEZER is not set 145# CONFIG_FREEZER is not set
135 146
136# 147#
@@ -161,6 +172,7 @@ CONFIG_S390_EXEC_PROTECT=y
161CONFIG_MARCH_Z900=y 172CONFIG_MARCH_Z900=y
162# CONFIG_MARCH_Z990 is not set 173# CONFIG_MARCH_Z990 is not set
163# CONFIG_MARCH_Z9_109 is not set 174# CONFIG_MARCH_Z9_109 is not set
175# CONFIG_MARCH_Z10 is not set
164CONFIG_PACK_STACK=y 176CONFIG_PACK_STACK=y
165# CONFIG_SMALL_STACK is not set 177# CONFIG_SMALL_STACK is not set
166CONFIG_CHECK_STACK=y 178CONFIG_CHECK_STACK=y
@@ -174,7 +186,6 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y
174# CONFIG_PREEMPT_NONE is not set 186# CONFIG_PREEMPT_NONE is not set
175# CONFIG_PREEMPT_VOLUNTARY is not set 187# CONFIG_PREEMPT_VOLUNTARY is not set
176CONFIG_PREEMPT=y 188CONFIG_PREEMPT=y
177# CONFIG_PREEMPT_RCU is not set
178CONFIG_ARCH_SPARSEMEM_ENABLE=y 189CONFIG_ARCH_SPARSEMEM_ENABLE=y
179CONFIG_ARCH_SPARSEMEM_DEFAULT=y 190CONFIG_ARCH_SPARSEMEM_DEFAULT=y
180CONFIG_ARCH_SELECT_MEMORY_MODEL=y 191CONFIG_ARCH_SELECT_MEMORY_MODEL=y
@@ -195,7 +206,6 @@ CONFIG_MEMORY_HOTREMOVE=y
195CONFIG_PAGEFLAGS_EXTENDED=y 206CONFIG_PAGEFLAGS_EXTENDED=y
196CONFIG_SPLIT_PTLOCK_CPUS=4 207CONFIG_SPLIT_PTLOCK_CPUS=4
197CONFIG_MIGRATION=y 208CONFIG_MIGRATION=y
198CONFIG_RESOURCES_64BIT=y
199CONFIG_PHYS_ADDR_T_64BIT=y 209CONFIG_PHYS_ADDR_T_64BIT=y
200CONFIG_ZONE_DMA_FLAG=1 210CONFIG_ZONE_DMA_FLAG=1
201CONFIG_BOUNCE=y 211CONFIG_BOUNCE=y
@@ -207,7 +217,6 @@ CONFIG_UNEVICTABLE_LRU=y
207# 217#
208CONFIG_MACHCHK_WARNING=y 218CONFIG_MACHCHK_WARNING=y
209CONFIG_QDIO=y 219CONFIG_QDIO=y
210# CONFIG_QDIO_DEBUG is not set
211CONFIG_CHSC_SCH=m 220CONFIG_CHSC_SCH=m
212 221
213# 222#
@@ -227,15 +236,13 @@ CONFIG_PFAULT=y
227# CONFIG_SHARED_KERNEL is not set 236# CONFIG_SHARED_KERNEL is not set
228# CONFIG_CMM is not set 237# CONFIG_CMM is not set
229# CONFIG_PAGE_STATES is not set 238# CONFIG_PAGE_STATES is not set
230CONFIG_VIRT_TIMER=y
231CONFIG_VIRT_CPU_ACCOUNTING=y
232# CONFIG_APPLDATA_BASE is not set 239# CONFIG_APPLDATA_BASE is not set
233CONFIG_HZ_100=y 240CONFIG_HZ_100=y
234# CONFIG_HZ_250 is not set 241# CONFIG_HZ_250 is not set
235# CONFIG_HZ_300 is not set 242# CONFIG_HZ_300 is not set
236# CONFIG_HZ_1000 is not set 243# CONFIG_HZ_1000 is not set
237CONFIG_HZ=100 244CONFIG_HZ=100
238# CONFIG_SCHED_HRTICK is not set 245CONFIG_SCHED_HRTICK=y
239CONFIG_S390_HYPFS_FS=y 246CONFIG_S390_HYPFS_FS=y
240CONFIG_KEXEC=y 247CONFIG_KEXEC=y
241# CONFIG_ZFCPDUMP is not set 248# CONFIG_ZFCPDUMP is not set
@@ -245,6 +252,7 @@ CONFIG_NET=y
245# 252#
246# Networking options 253# Networking options
247# 254#
255CONFIG_COMPAT_NET_DEV_OPS=y
248CONFIG_PACKET=y 256CONFIG_PACKET=y
249# CONFIG_PACKET_MMAP is not set 257# CONFIG_PACKET_MMAP is not set
250CONFIG_UNIX=y 258CONFIG_UNIX=y
@@ -383,6 +391,7 @@ CONFIG_NET_SCH_TBF=m
383CONFIG_NET_SCH_GRED=m 391CONFIG_NET_SCH_GRED=m
384CONFIG_NET_SCH_DSMARK=m 392CONFIG_NET_SCH_DSMARK=m
385# CONFIG_NET_SCH_NETEM is not set 393# CONFIG_NET_SCH_NETEM is not set
394# CONFIG_NET_SCH_DRR is not set
386# CONFIG_NET_SCH_INGRESS is not set 395# CONFIG_NET_SCH_INGRESS is not set
387 396
388# 397#
@@ -400,6 +409,7 @@ CONFIG_CLS_U32_MARK=y
400CONFIG_NET_CLS_RSVP=m 409CONFIG_NET_CLS_RSVP=m
401CONFIG_NET_CLS_RSVP6=m 410CONFIG_NET_CLS_RSVP6=m
402CONFIG_NET_CLS_FLOW=m 411CONFIG_NET_CLS_FLOW=m
412# CONFIG_NET_CLS_CGROUP is not set
403# CONFIG_NET_EMATCH is not set 413# CONFIG_NET_EMATCH is not set
404CONFIG_NET_CLS_ACT=y 414CONFIG_NET_CLS_ACT=y
405CONFIG_NET_ACT_POLICE=y 415CONFIG_NET_ACT_POLICE=y
@@ -411,6 +421,7 @@ CONFIG_NET_ACT_NAT=m
411# CONFIG_NET_ACT_SKBEDIT is not set 421# CONFIG_NET_ACT_SKBEDIT is not set
412# CONFIG_NET_CLS_IND is not set 422# CONFIG_NET_CLS_IND is not set
413CONFIG_NET_SCH_FIFO=y 423CONFIG_NET_SCH_FIFO=y
424# CONFIG_DCB is not set
414 425
415# 426#
416# Network testing 427# Network testing
@@ -428,6 +439,7 @@ CONFIG_CAN_VCAN=m
428# CONFIG_CAN_DEBUG_DEVICES is not set 439# CONFIG_CAN_DEBUG_DEVICES is not set
429# CONFIG_AF_RXRPC is not set 440# CONFIG_AF_RXRPC is not set
430# CONFIG_PHONET is not set 441# CONFIG_PHONET is not set
442# CONFIG_WIMAX is not set
431# CONFIG_RFKILL is not set 443# CONFIG_RFKILL is not set
432# CONFIG_NET_9P is not set 444# CONFIG_NET_9P is not set
433# CONFIG_PCMCIA is not set 445# CONFIG_PCMCIA is not set
@@ -475,11 +487,15 @@ CONFIG_DASD_DIAG=y
475CONFIG_DASD_EER=y 487CONFIG_DASD_EER=y
476CONFIG_VIRTIO_BLK=m 488CONFIG_VIRTIO_BLK=m
477CONFIG_MISC_DEVICES=y 489CONFIG_MISC_DEVICES=y
478# CONFIG_EEPROM_93CX6 is not set
479# CONFIG_ENCLOSURE_SERVICES is not set 490# CONFIG_ENCLOSURE_SERVICES is not set
480# CONFIG_C2PORT is not set 491# CONFIG_C2PORT is not set
481 492
482# 493#
494# EEPROM support
495#
496# CONFIG_EEPROM_93CX6 is not set
497
498#
483# SCSI device support 499# SCSI device support
484# 500#
485# CONFIG_RAID_ATTRS is not set 501# CONFIG_RAID_ATTRS is not set
@@ -520,6 +536,7 @@ CONFIG_SCSI_FC_ATTRS=y
520# CONFIG_SCSI_SRP_ATTRS is not set 536# CONFIG_SCSI_SRP_ATTRS is not set
521CONFIG_SCSI_LOWLEVEL=y 537CONFIG_SCSI_LOWLEVEL=y
522# CONFIG_ISCSI_TCP is not set 538# CONFIG_ISCSI_TCP is not set
539# CONFIG_LIBFC is not set
523# CONFIG_SCSI_DEBUG is not set 540# CONFIG_SCSI_DEBUG is not set
524CONFIG_ZFCP=y 541CONFIG_ZFCP=y
525CONFIG_SCSI_DH=m 542CONFIG_SCSI_DH=m
@@ -566,6 +583,10 @@ CONFIG_NET_ETHERNET=y
566CONFIG_NETDEV_1000=y 583CONFIG_NETDEV_1000=y
567CONFIG_NETDEV_10000=y 584CONFIG_NETDEV_10000=y
568# CONFIG_TR is not set 585# CONFIG_TR is not set
586
587#
588# Enable WiMAX (Networking options) to see the WiMAX drivers
589#
569# CONFIG_WAN is not set 590# CONFIG_WAN is not set
570 591
571# 592#
@@ -593,9 +614,11 @@ CONFIG_VIRTIO_NET=m
593# 614#
594CONFIG_DEVKMEM=y 615CONFIG_DEVKMEM=y
595CONFIG_UNIX98_PTYS=y 616CONFIG_UNIX98_PTYS=y
617# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
596CONFIG_LEGACY_PTYS=y 618CONFIG_LEGACY_PTYS=y
597CONFIG_LEGACY_PTY_COUNT=256 619CONFIG_LEGACY_PTY_COUNT=256
598CONFIG_HVC_DRIVER=y 620CONFIG_HVC_DRIVER=y
621CONFIG_HVC_IUCV=y
599CONFIG_VIRTIO_CONSOLE=y 622CONFIG_VIRTIO_CONSOLE=y
600CONFIG_HW_RANDOM=m 623CONFIG_HW_RANDOM=m
601CONFIG_HW_RANDOM_VIRTIO=m 624CONFIG_HW_RANDOM_VIRTIO=m
@@ -645,7 +668,6 @@ CONFIG_S390_VMUR=m
645# CONFIG_NEW_LEDS is not set 668# CONFIG_NEW_LEDS is not set
646CONFIG_ACCESSIBILITY=y 669CONFIG_ACCESSIBILITY=y
647# CONFIG_STAGING is not set 670# CONFIG_STAGING is not set
648CONFIG_STAGING_EXCLUDE_BUILD=y
649 671
650# 672#
651# File systems 673# File systems
@@ -668,6 +690,7 @@ CONFIG_FILE_LOCKING=y
668# CONFIG_XFS_FS is not set 690# CONFIG_XFS_FS is not set
669# CONFIG_GFS2_FS is not set 691# CONFIG_GFS2_FS is not set
670# CONFIG_OCFS2_FS is not set 692# CONFIG_OCFS2_FS is not set
693# CONFIG_BTRFS_FS is not set
671CONFIG_DNOTIFY=y 694CONFIG_DNOTIFY=y
672CONFIG_INOTIFY=y 695CONFIG_INOTIFY=y
673CONFIG_INOTIFY_USER=y 696CONFIG_INOTIFY_USER=y
@@ -703,10 +726,7 @@ CONFIG_TMPFS_POSIX_ACL=y
703# CONFIG_HUGETLBFS is not set 726# CONFIG_HUGETLBFS is not set
704# CONFIG_HUGETLB_PAGE is not set 727# CONFIG_HUGETLB_PAGE is not set
705CONFIG_CONFIGFS_FS=m 728CONFIG_CONFIGFS_FS=m
706 729CONFIG_MISC_FILESYSTEMS=y
707#
708# Miscellaneous filesystems
709#
710# CONFIG_ADFS_FS is not set 730# CONFIG_ADFS_FS is not set
711# CONFIG_AFFS_FS is not set 731# CONFIG_AFFS_FS is not set
712# CONFIG_HFS_FS is not set 732# CONFIG_HFS_FS is not set
@@ -715,6 +735,7 @@ CONFIG_CONFIGFS_FS=m
715# CONFIG_BFS_FS is not set 735# CONFIG_BFS_FS is not set
716# CONFIG_EFS_FS is not set 736# CONFIG_EFS_FS is not set
717# CONFIG_CRAMFS is not set 737# CONFIG_CRAMFS is not set
738# CONFIG_SQUASHFS is not set
718# CONFIG_VXFS_FS is not set 739# CONFIG_VXFS_FS is not set
719# CONFIG_MINIX_FS is not set 740# CONFIG_MINIX_FS is not set
720# CONFIG_OMFS_FS is not set 741# CONFIG_OMFS_FS is not set
@@ -808,6 +829,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
808CONFIG_DEBUG_MEMORY_INIT=y 829CONFIG_DEBUG_MEMORY_INIT=y
809# CONFIG_DEBUG_LIST is not set 830# CONFIG_DEBUG_LIST is not set
810# CONFIG_DEBUG_SG is not set 831# CONFIG_DEBUG_SG is not set
832# CONFIG_DEBUG_NOTIFIERS is not set
811# CONFIG_FRAME_POINTER is not set 833# CONFIG_FRAME_POINTER is not set
812# CONFIG_RCU_TORTURE_TEST is not set 834# CONFIG_RCU_TORTURE_TEST is not set
813# CONFIG_RCU_CPU_STALL_DETECTOR is not set 835# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -818,15 +840,19 @@ CONFIG_DEBUG_MEMORY_INIT=y
818# CONFIG_FAULT_INJECTION is not set 840# CONFIG_FAULT_INJECTION is not set
819# CONFIG_LATENCYTOP is not set 841# CONFIG_LATENCYTOP is not set
820CONFIG_SYSCTL_SYSCALL_CHECK=y 842CONFIG_SYSCTL_SYSCALL_CHECK=y
843CONFIG_HAVE_FUNCTION_TRACER=y
821 844
822# 845#
823# Tracers 846# Tracers
824# 847#
848# CONFIG_FUNCTION_TRACER is not set
825# CONFIG_IRQSOFF_TRACER is not set 849# CONFIG_IRQSOFF_TRACER is not set
826# CONFIG_PREEMPT_TRACER is not set 850# CONFIG_PREEMPT_TRACER is not set
827# CONFIG_SCHED_TRACER is not set 851# CONFIG_SCHED_TRACER is not set
828# CONFIG_CONTEXT_SWITCH_TRACER is not set 852# CONFIG_CONTEXT_SWITCH_TRACER is not set
829# CONFIG_BOOT_TRACER is not set 853# CONFIG_BOOT_TRACER is not set
854# CONFIG_TRACE_BRANCH_PROFILING is not set
855# CONFIG_STACK_TRACER is not set
830# CONFIG_DYNAMIC_PRINTK_DEBUG is not set 856# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
831CONFIG_SAMPLES=y 857CONFIG_SAMPLES=y
832# CONFIG_SAMPLE_KOBJECT is not set 858# CONFIG_SAMPLE_KOBJECT is not set
@@ -847,11 +873,17 @@ CONFIG_CRYPTO=y
847# 873#
848CONFIG_CRYPTO_FIPS=y 874CONFIG_CRYPTO_FIPS=y
849CONFIG_CRYPTO_ALGAPI=y 875CONFIG_CRYPTO_ALGAPI=y
850CONFIG_CRYPTO_AEAD=y 876CONFIG_CRYPTO_ALGAPI2=y
877CONFIG_CRYPTO_AEAD=m
878CONFIG_CRYPTO_AEAD2=y
851CONFIG_CRYPTO_BLKCIPHER=y 879CONFIG_CRYPTO_BLKCIPHER=y
852CONFIG_CRYPTO_HASH=y 880CONFIG_CRYPTO_BLKCIPHER2=y
853CONFIG_CRYPTO_RNG=y 881CONFIG_CRYPTO_HASH=m
882CONFIG_CRYPTO_HASH2=y
883CONFIG_CRYPTO_RNG=m
884CONFIG_CRYPTO_RNG2=y
854CONFIG_CRYPTO_MANAGER=y 885CONFIG_CRYPTO_MANAGER=y
886CONFIG_CRYPTO_MANAGER2=y
855CONFIG_CRYPTO_GF128MUL=m 887CONFIG_CRYPTO_GF128MUL=m
856# CONFIG_CRYPTO_NULL is not set 888# CONFIG_CRYPTO_NULL is not set
857# CONFIG_CRYPTO_CRYPTD is not set 889# CONFIG_CRYPTO_CRYPTD is not set
@@ -885,7 +917,7 @@ CONFIG_CRYPTO_HMAC=m
885# 917#
886# Digest 918# Digest
887# 919#
888# CONFIG_CRYPTO_CRC32C is not set 920CONFIG_CRYPTO_CRC32C=m
889# CONFIG_CRYPTO_MD4 is not set 921# CONFIG_CRYPTO_MD4 is not set
890CONFIG_CRYPTO_MD5=m 922CONFIG_CRYPTO_MD5=m
891# CONFIG_CRYPTO_MICHAEL_MIC is not set 923# CONFIG_CRYPTO_MICHAEL_MIC is not set
@@ -942,6 +974,7 @@ CONFIG_S390_PRNG=m
942# Library routines 974# Library routines
943# 975#
944CONFIG_BITREVERSE=m 976CONFIG_BITREVERSE=m
977CONFIG_GENERIC_FIND_LAST_BIT=y
945# CONFIG_CRC_CCITT is not set 978# CONFIG_CRC_CCITT is not set
946# CONFIG_CRC16 is not set 979# CONFIG_CRC16 is not set
947CONFIG_CRC_T10DIF=y 980CONFIG_CRC_T10DIF=y
kwb">uint8_t throttle_buf[128]; uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */ /* inbuf is for packet reassembly. leave a little room for leftovers. */ uint8_t inbuf[HVSI_MAX_PACKET + HVSI_MAX_READ]; uint8_t *inbuf_end; int n_throttle; int n_outbuf; uint32_t vtermno; uint32_t virq; atomic_t seqno; /* HVSI packet sequence number */ uint16_t mctrl; uint8_t state; /* HVSI protocol state */ uint8_t flags; #ifdef CONFIG_MAGIC_SYSRQ uint8_t sysrq; #endif /* CONFIG_MAGIC_SYSRQ */ }; static struct hvsi_struct hvsi_ports[MAX_NR_HVSI_CONSOLES]; static struct tty_driver *hvsi_driver; static int hvsi_count; static int (*hvsi_wait)(struct hvsi_struct *hp, int state); enum HVSI_PROTOCOL_STATE { HVSI_CLOSED, HVSI_WAIT_FOR_VER_RESPONSE, HVSI_WAIT_FOR_VER_QUERY, HVSI_OPEN, HVSI_WAIT_FOR_MCTRL_RESPONSE, HVSI_FSP_DIED, }; #define HVSI_CONSOLE 0x1 #define VS_DATA_PACKET_HEADER 0xff #define VS_CONTROL_PACKET_HEADER 0xfe #define VS_QUERY_PACKET_HEADER 0xfd #define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc /* control verbs */ #define VSV_SET_MODEM_CTL 1 /* to service processor only */ #define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */ #define VSV_CLOSE_PROTOCOL 3 /* query verbs */ #define VSV_SEND_VERSION_NUMBER 1 #define VSV_SEND_MODEM_CTL_STATUS 2 /* yes, these masks are not consecutive. */ #define HVSI_TSDTR 0x01 #define HVSI_TSCD 0x20 struct hvsi_header { uint8_t type; uint8_t len; uint16_t seqno; } __attribute__((packed)); struct hvsi_data { uint8_t type; uint8_t len; uint16_t seqno; uint8_t data[HVSI_MAX_OUTGOING_DATA]; } __attribute__((packed)); struct hvsi_control { uint8_t type; uint8_t len; uint16_t seqno; uint16_t verb; /* optional depending on verb: */ uint32_t word; uint32_t mask; } __attribute__((packed)); struct hvsi_query { uint8_t type; uint8_t len; uint16_t seqno; uint16_t verb; } __attribute__((packed)); struct hvsi_query_response { uint8_t type; uint8_t len; uint16_t seqno; uint16_t verb; uint16_t query_seqno; union { uint8_t version; uint32_t mctrl_word; } u; } __attribute__((packed)); static inline int is_console(struct hvsi_struct *hp) { return hp->flags & HVSI_CONSOLE; } static inline int is_open(struct hvsi_struct *hp) { /* if we're waiting for an mctrl then we're already open */ return (hp->state == HVSI_OPEN) || (hp->state == HVSI_WAIT_FOR_MCTRL_RESPONSE); } static inline void print_state(struct hvsi_struct *hp) { #ifdef DEBUG static const char *state_names[] = { "HVSI_CLOSED", "HVSI_WAIT_FOR_VER_RESPONSE", "HVSI_WAIT_FOR_VER_QUERY", "HVSI_OPEN", "HVSI_WAIT_FOR_MCTRL_RESPONSE", "HVSI_FSP_DIED", }; const char *name = state_names[hp->state]; if (hp->state > ARRAY_SIZE(state_names)) name = "UNKNOWN"; pr_debug("hvsi%i: state = %s\n", hp->index, name); #endif /* DEBUG */ } static inline void __set_state(struct hvsi_struct *hp, int state) { hp->state = state; print_state(hp); wake_up_all(&hp->stateq); } static inline void set_state(struct hvsi_struct *hp, int state) { unsigned long flags; spin_lock_irqsave(&hp->lock, flags); __set_state(hp, state); spin_unlock_irqrestore(&hp->lock, flags); } static inline int len_packet(const uint8_t *packet) { return (int)((struct hvsi_header *)packet)->len; } static inline int is_header(const uint8_t *packet) { struct hvsi_header *header = (struct hvsi_header *)packet; return header->type >= VS_QUERY_RESPONSE_PACKET_HEADER; } static inline int got_packet(const struct hvsi_struct *hp, uint8_t *packet) { if (hp->inbuf_end < packet + sizeof(struct hvsi_header)) return 0; /* don't even have the packet header */ if (hp->inbuf_end < (packet + len_packet(packet))) return 0; /* don't have the rest of the packet */ return 1; } /* shift remaining bytes in packetbuf down */ static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to) { int remaining = (int)(hp->inbuf_end - read_to); pr_debug("%s: %i chars remain\n", __func__, remaining); if (read_to != hp->inbuf) memmove(hp->inbuf, read_to, remaining); hp->inbuf_end = hp->inbuf + remaining; } #ifdef DEBUG #define dbg_dump_packet(packet) dump_packet(packet) #define dbg_dump_hex(data, len) dump_hex(data, len) #else #define dbg_dump_packet(packet) do { } while (0) #define dbg_dump_hex(data, len) do { } while (0) #endif static void dump_hex(const uint8_t *data, int len) { int i; printk(" "); for (i=0; i < len; i++) printk("%.2x", data[i]); printk("\n "); for (i=0; i < len; i++) { if (isprint(data[i])) printk("%c", data[i]); else printk("."); } printk("\n"); } static void dump_packet(uint8_t *packet) { struct hvsi_header *header = (struct hvsi_header *)packet; printk("type 0x%x, len %i, seqno %i:\n", header->type, header->len, header->seqno); dump_hex(packet, header->len); } static int hvsi_read(struct hvsi_struct *hp, char *buf, int count) { unsigned long got; got = hvc_get_chars(hp->vtermno, buf, count); return got; } static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet, struct tty_struct **to_hangup, struct hvsi_struct **to_handshake) { struct hvsi_control *header = (struct hvsi_control *)packet; switch (header->verb) { case VSV_MODEM_CTL_UPDATE: if ((header->word & HVSI_TSCD) == 0) { /* CD went away; no more connection */ pr_debug("hvsi%i: CD dropped\n", hp->index); hp->mctrl &= TIOCM_CD; /* If userland hasn't done an open(2) yet, hp->tty is NULL. */ if (hp->tty && !(hp->tty->flags & CLOCAL)) *to_hangup = hp->tty; } break; case VSV_CLOSE_PROTOCOL: pr_debug("hvsi%i: service processor came back\n", hp->index); if (hp->state != HVSI_CLOSED) { *to_handshake = hp; } break; default: printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ", hp->index); dump_packet(packet); break; } } static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet) { struct hvsi_query_response *resp = (struct hvsi_query_response *)packet; switch (hp->state) { case HVSI_WAIT_FOR_VER_RESPONSE: __set_state(hp, HVSI_WAIT_FOR_VER_QUERY); break; case HVSI_WAIT_FOR_MCTRL_RESPONSE: hp->mctrl = 0; if (resp->u.mctrl_word & HVSI_TSDTR) hp->mctrl |= TIOCM_DTR; if (resp->u.mctrl_word & HVSI_TSCD) hp->mctrl |= TIOCM_CD; __set_state(hp, HVSI_OPEN); break; default: printk(KERN_ERR "hvsi%i: unexpected query response: ", hp->index); dump_packet(packet); break; } } /* respond to service processor's version query */ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno) { struct hvsi_query_response packet __ALIGNED__; int wrote; packet.type = VS_QUERY_RESPONSE_PACKET_HEADER; packet.len = sizeof(struct hvsi_query_response); packet.seqno = atomic_inc_return(&hp->seqno); packet.verb = VSV_SEND_VERSION_NUMBER; packet.u.version = HVSI_VERSION; packet.query_seqno = query_seqno+1; pr_debug("%s: sending %i bytes\n", __func__, packet.len); dbg_dump_hex((uint8_t*)&packet, packet.len); wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len); if (wrote != packet.len) { printk(KERN_ERR "hvsi%i: couldn't send query response!\n", hp->index); return -EIO; } return 0; } static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet) { struct hvsi_query *query = (struct hvsi_query *)packet; switch (hp->state) { case HVSI_WAIT_FOR_VER_QUERY: hvsi_version_respond(hp, query->seqno); __set_state(hp, HVSI_OPEN); break; default: printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index); dump_packet(packet); break; } } static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len) { int i; for (i=0; i < len; i++) { char c = buf[i]; #ifdef CONFIG_MAGIC_SYSRQ if (c == '\0') { hp->sysrq = 1; continue; } else if (hp->sysrq) { handle_sysrq(c, hp->tty); hp->sysrq = 0; continue; } #endif /* CONFIG_MAGIC_SYSRQ */ tty_insert_flip_char(hp->tty, c, 0); } } /* * We could get 252 bytes of data at once here. But the tty layer only * throttles us at TTY_THRESHOLD_THROTTLE (128) bytes, so we could overflow * it. Accordingly we won't send more than 128 bytes at a time to the flip * buffer, which will give the tty buffer a chance to throttle us. Should the * value of TTY_THRESHOLD_THROTTLE change in n_tty.c, this code should be * revisited. */ #define TTY_THRESHOLD_THROTTLE 128 static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp, const uint8_t *packet) { const struct hvsi_header *header = (const struct hvsi_header *)packet; const uint8_t *data = packet + sizeof(struct hvsi_header); int datalen = header->len - sizeof(struct hvsi_header); int overflow = datalen - TTY_THRESHOLD_THROTTLE; pr_debug("queueing %i chars '%.*s'\n", datalen, datalen, data); if (datalen == 0) return NULL; if (overflow > 0) { pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __func__); datalen = TTY_THRESHOLD_THROTTLE; } hvsi_insert_chars(hp, data, datalen); if (overflow > 0) { /* * we still have more data to deliver, so we need to save off the * overflow and send it later */ pr_debug("%s: deferring overflow\n", __func__); memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow); hp->n_throttle = overflow; } return hp->tty; } /* * Returns true/false indicating data successfully read from hypervisor. * Used both to get packets for tty connections and to advance the state * machine during console handshaking (in which case tty = NULL and we ignore * incoming data). */ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip, struct tty_struct **hangup, struct hvsi_struct **handshake) { uint8_t *packet = hp->inbuf; int chunklen; *flip = NULL; *hangup = NULL; *handshake = NULL; chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ); if (chunklen == 0) { pr_debug("%s: 0-length read\n", __func__); return 0; } pr_debug("%s: got %i bytes\n", __func__, chunklen); dbg_dump_hex(hp->inbuf_end, chunklen); hp->inbuf_end += chunklen; /* handle all completed packets */ while ((packet < hp->inbuf_end) && got_packet(hp, packet)) { struct hvsi_header *header = (struct hvsi_header *)packet; if (!is_header(packet)) { printk(KERN_ERR "hvsi%i: got malformed packet\n", hp->index); /* skip bytes until we find a header or run out of data */ while ((packet < hp->inbuf_end) && (!is_header(packet))) packet++; continue; } pr_debug("%s: handling %i-byte packet\n", __func__, len_packet(packet)); dbg_dump_packet(packet); switch (header->type) { case VS_DATA_PACKET_HEADER: if (!is_open(hp)) break; if (hp->tty == NULL) break; /* no tty buffer to put data in */ *flip = hvsi_recv_data(hp, packet); break; case VS_CONTROL_PACKET_HEADER: hvsi_recv_control(hp, packet, hangup, handshake); break; case VS_QUERY_RESPONSE_PACKET_HEADER: hvsi_recv_response(hp, packet); break; case VS_QUERY_PACKET_HEADER: hvsi_recv_query(hp, packet); break; default: printk(KERN_ERR "hvsi%i: unknown HVSI packet type 0x%x\n", hp->index, header->type); dump_packet(packet); break; } packet += len_packet(packet); if (*hangup || *handshake) { pr_debug("%s: hangup or handshake\n", __func__); /* * we need to send the hangup now before receiving any more data. * If we get "data, hangup, data", we can't deliver the second * data before the hangup. */ break; } } compact_inbuf(hp, packet); return 1; } static void hvsi_send_overflow(struct hvsi_struct *hp) { pr_debug("%s: delivering %i bytes overflow\n", __func__, hp->n_throttle); hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle); hp->n_throttle = 0; } /* * must get all pending data because we only get an irq on empty->non-empty * transition */ static irqreturn_t hvsi_interrupt(int irq, void *arg) { struct hvsi_struct *hp = (struct hvsi_struct *)arg; struct tty_struct *flip; struct tty_struct *hangup; struct hvsi_struct *handshake; unsigned long flags; int again = 1; pr_debug("%s\n", __func__); while (again) { spin_lock_irqsave(&hp->lock, flags); again = hvsi_load_chunk(hp, &flip, &hangup, &handshake); spin_unlock_irqrestore(&hp->lock, flags); /* * we have to call tty_flip_buffer_push() and tty_hangup() outside our * spinlock. But we also have to keep going until we've read all the * available data. */ if (flip) { /* there was data put in the tty flip buffer */ tty_flip_buffer_push(flip); flip = NULL; } if (hangup) { tty_hangup(hangup); } if (handshake) { pr_debug("hvsi%i: attempting re-handshake\n", handshake->index); schedule_work(&handshake->handshaker); } } spin_lock_irqsave(&hp->lock, flags); if (hp->tty && hp->n_throttle && (!test_bit(TTY_THROTTLED, &hp->tty->flags))) { /* we weren't hung up and we weren't throttled, so we can deliver the * rest now */ flip = hp->tty; hvsi_send_overflow(hp); } spin_unlock_irqrestore(&hp->lock, flags); if (flip) { tty_flip_buffer_push(flip); } return IRQ_HANDLED; } /* for boot console, before the irq handler is running */ static int __init poll_for_state(struct hvsi_struct *hp, int state) { unsigned long end_jiffies = jiffies + HVSI_TIMEOUT; for (;;) { hvsi_interrupt(hp->virq, (void *)hp); /* get pending data */ if (hp->state == state) return 0; mdelay(5); if (time_after(jiffies, end_jiffies)) return -EIO; } } /* wait for irq handler to change our state */ static int wait_for_state(struct hvsi_struct *hp, int state) { int ret = 0; if (!wait_event_timeout(hp->stateq, (hp->state == state), HVSI_TIMEOUT)) ret = -EIO; return ret; } static int hvsi_query(struct hvsi_struct *hp, uint16_t verb) { struct hvsi_query packet __ALIGNED__; int wrote; packet.type = VS_QUERY_PACKET_HEADER; packet.len = sizeof(struct hvsi_query); packet.seqno = atomic_inc_return(&hp->seqno); packet.verb = verb; pr_debug("%s: sending %i bytes\n", __func__, packet.len); dbg_dump_hex((uint8_t*)&packet, packet.len); wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len); if (wrote != packet.len) { printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index, wrote); return -EIO; } return 0; } static int hvsi_get_mctrl(struct hvsi_struct *hp) { int ret; set_state(hp, HVSI_WAIT_FOR_MCTRL_RESPONSE); hvsi_query(hp, VSV_SEND_MODEM_CTL_STATUS); ret = hvsi_wait(hp, HVSI_OPEN); if (ret < 0) { printk(KERN_ERR "hvsi%i: didn't get modem flags\n", hp->index); set_state(hp, HVSI_OPEN); return ret; } pr_debug("%s: mctrl 0x%x\n", __func__, hp->mctrl); return 0; } /* note that we can only set DTR */ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl) { struct hvsi_control packet __ALIGNED__; int wrote; packet.type = VS_CONTROL_PACKET_HEADER, packet.seqno = atomic_inc_return(&hp->seqno); packet.len = sizeof(struct hvsi_control); packet.verb = VSV_SET_MODEM_CTL; packet.mask = HVSI_TSDTR; if (mctrl & TIOCM_DTR) packet.word = HVSI_TSDTR; pr_debug("%s: sending %i bytes\n", __func__, packet.len); dbg_dump_hex((uint8_t*)&packet, packet.len); wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len); if (wrote != packet.len) { printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index); return -EIO; } return 0; } static void hvsi_drain_input(struct hvsi_struct *hp) { uint8_t buf[HVSI_MAX_READ] __ALIGNED__; unsigned long end_jiffies = jiffies + HVSI_TIMEOUT; while (time_before(end_jiffies, jiffies)) if (0 == hvsi_read(hp, buf, HVSI_MAX_READ)) break; } static int hvsi_handshake(struct hvsi_struct *hp) { int ret; /* * We could have a CLOSE or other data waiting for us before we even try * to open; try to throw it all away so we don't get confused. (CLOSE * is the first message sent up the pipe when the FSP comes online. We * need to distinguish between "it came up a while ago and we're the first * user" and "it was just reset before it saw our handshake packet".) */ hvsi_drain_input(hp); set_state(hp, HVSI_WAIT_FOR_VER_RESPONSE); ret = hvsi_query(hp, VSV_SEND_VERSION_NUMBER); if (ret < 0) { printk(KERN_ERR "hvsi%i: couldn't send version query\n", hp->index); return ret; } ret = hvsi_wait(hp, HVSI_OPEN); if (ret < 0) return ret; return 0; } static void hvsi_handshaker(struct work_struct *work) { struct hvsi_struct *hp = container_of(work, struct hvsi_struct, handshaker); if (hvsi_handshake(hp) >= 0) return; printk(KERN_ERR "hvsi%i: re-handshaking failed\n", hp->index); if (is_console(hp)) { /* * ttys will re-attempt the handshake via hvsi_open, but * the console will not. */ printk(KERN_ERR "hvsi%i: lost console!\n", hp->index); } } static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count) { struct hvsi_data packet __ALIGNED__; int ret; BUG_ON(count > HVSI_MAX_OUTGOING_DATA); packet.type = VS_DATA_PACKET_HEADER; packet.seqno = atomic_inc_return(&hp->seqno); packet.len = count + sizeof(struct hvsi_header); memcpy(&packet.data, buf, count); ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len); if (ret == packet.len) { /* return the number of chars written, not the packet length */ return count; } return ret; /* return any errors */ } static void hvsi_close_protocol(struct hvsi_struct *hp) { struct hvsi_control packet __ALIGNED__; packet.type = VS_CONTROL_PACKET_HEADER; packet.seqno = atomic_inc_return(&hp->seqno); packet.len = 6; packet.verb = VSV_CLOSE_PROTOCOL; pr_debug("%s: sending %i bytes\n", __func__, packet.len); dbg_dump_hex((uint8_t*)&packet, packet.len); hvc_put_chars(hp->vtermno, (char *)&packet, packet.len); } static int hvsi_open(struct tty_struct *tty, struct file *filp) { struct hvsi_struct *hp; unsigned long flags; int line = tty->index; int ret; pr_debug("%s\n", __func__); if (line < 0 || line >= hvsi_count) return -ENODEV; hp = &hvsi_ports[line]; tty->driver_data = hp; mb(); if (hp->state == HVSI_FSP_DIED) return -EIO; spin_lock_irqsave(&hp->lock, flags); hp->tty = tty; hp->count++; atomic_set(&hp->seqno, 0); h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE); spin_unlock_irqrestore(&hp->lock, flags); if (is_console(hp)) return 0; /* this has already been handshaked as the console */ ret = hvsi_handshake(hp); if (ret < 0) { printk(KERN_ERR "%s: HVSI handshaking failed\n", tty->name); return ret; } ret = hvsi_get_mctrl(hp); if (ret < 0) { printk(KERN_ERR "%s: couldn't get initial modem flags\n", tty->name); return ret; } ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR); if (ret < 0) { printk(KERN_ERR "%s: couldn't set DTR\n", tty->name); return ret; } return 0; } /* wait for hvsi_write_worker to empty hp->outbuf */ static void hvsi_flush_output(struct hvsi_struct *hp) { wait_event_timeout(hp->emptyq, (hp->n_outbuf <= 0), HVSI_TIMEOUT); /* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */ cancel_delayed_work(&hp->writer); flush_scheduled_work(); /* * it's also possible that our timeout expired and hvsi_write_worker * didn't manage to push outbuf. poof. */ hp->n_outbuf = 0; } static void hvsi_close(struct tty_struct *tty, struct file *filp) { struct hvsi_struct *hp = tty->driver_data; unsigned long flags; pr_debug("%s\n", __func__); if (tty_hung_up_p(filp)) return; spin_lock_irqsave(&hp->lock, flags); if (--hp->count == 0) {